Initial commit

This commit is contained in:
2023-05-11 18:33:53 +02:00
commit 614d7b9241
46 changed files with 1974 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
package de.mattv.quarry
import mcjty.theoneprobe.api.IProbeHitData
import mcjty.theoneprobe.api.IProbeInfo
import mcjty.theoneprobe.api.IProbeInfoAccessor
import mcjty.theoneprobe.api.ProbeMode
import net.minecraft.core.BlockPos
import net.minecraft.network.chat.TextComponent
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.SoundType
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.material.Material
import net.minecraft.world.phys.BlockHitResult
class QuarryBlock : Block(Properties.of(Material.STONE).sound(SoundType.METAL).strength(5.0f, 10000.0f)), EntityBlock, IProbeInfoAccessor {
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity? = QuarryMod.QUARRY_TILE.get().create(pos, state)
override fun <T : BlockEntity?> getTicker(level: Level, state: BlockState, type: BlockEntityType<T>): BlockEntityTicker<T>? =
if (type == QuarryMod.QUARRY_TILE.get()) QuarryTileTicker() else null
override fun use(state: BlockState, level: Level, pos: BlockPos, player: Player, hand: InteractionHand, result: BlockHitResult): InteractionResult {
val be = level.getBlockEntity(pos)
if (!level.isClientSide() && !player.isSecondaryUseActive && hand == InteractionHand.MAIN_HAND && player.getItemInHand(hand).isEmpty && be is QuarryTile) {
player.displayClientMessage(TextComponent(be.playerInfo()), true)
return InteractionResult.PASS
}
return super.use(state, level, pos, player, hand, result)
}
private fun dropUpgradeItem(level: Level, pos: BlockPos, count: Int, item: Item) {
val x = pos.x.toDouble()
val y = pos.y.toDouble()
val z = pos.z.toDouble()
var toDrop = count
while (toDrop > 64) {
level.addFreshEntity(ItemEntity(level, x, y, z, ItemStack(item, 64)))
toDrop -= 64
}
if (toDrop > 0)
level.addFreshEntity(ItemEntity(level, x, y, z, ItemStack(item, toDrop)))
}
override fun playerDestroy(level: Level, player: Player, pos: BlockPos, state: BlockState, be: BlockEntity?, tool: ItemStack) {
if (!level.isClientSide() && be is QuarryTile) {
val toDrop = be.getUpgradesToDrop()
dropUpgradeItem(level, pos, toDrop.a, QuarryMod.QUARRY_SPEED_UPGRADE.get())
dropUpgradeItem(level, pos, toDrop.b, QuarryMod.QUARRY_FORTUNE_UPGRADE.get())
}
super.playerDestroy(level, player, pos, state, be, tool)
}
override fun addProbeInfo(mode: ProbeMode?, info: IProbeInfo?, player: Player?, level: Level?, state: BlockState?, data: IProbeHitData?) {
val be = level!!.getBlockEntity(data!!.pos)
if (be is QuarryTile)
be.probeInfo(info!!)
}
}

View File

@@ -0,0 +1,34 @@
package de.mattv.quarry
import net.minecraft.core.BlockPos
import net.minecraft.nbt.CompoundTag
class QuarryChunk(val x: Int, val z: Int) {
constructor(pos: BlockPos) : this(
pos.x.let {
var i = it
if (i < 0) i -= 16
(i / 16) * 16
},
pos.z.let {
var i = it
if (i < 0) i -= 16
(i / 16) * 16
}
)
constructor(tag: CompoundTag) : this(
tag.getInt("x"),
tag.getInt("z")
)
fun save(): CompoundTag = CompoundTag().apply {
putInt("x", x)
putInt("z", z)
}
fun asPos(): BlockPos = BlockPos(x, 0, z)
fun min(other: QuarryChunk) = QuarryChunk(kotlin.math.min(x, other.x), kotlin.math.min(z, other.z))
fun max(other: QuarryChunk) = QuarryChunk(kotlin.math.max(x, other.x), kotlin.math.max(z, other.z))
}

View File

@@ -0,0 +1,116 @@
package de.mattv.quarry
import net.minecraft.core.BlockPos
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TextComponent
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResultHolder
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.CreativeModeTab
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.level.ClipContext
import net.minecraft.world.level.Level
class QuarryController : Item(Properties().tab(CreativeModeTab.TAB_MISC).stacksTo(1)) {
private var areaMode = false
private var areaModeFirstPos: QuarryChunk? = null
private var quarry: BlockPos? = null
override fun use(level: Level, player: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
if (!level.isClientSide() && hand == InteractionHand.MAIN_HAND) {
val item = player.getItemInHand(hand)
load(item)
if (player.isSecondaryUseActive) {
val ray = getPlayerPOVHitResult(level, player, ClipContext.Fluid.NONE)
val block = ray.blockPos
val be = level.getBlockEntity(block)
if (be is QuarryTile) {
quarry = block
player.displayClientMessage(TextComponent("Bound controller to ${block.x}, ${block.y}, ${block.z}"), true)
save(item)
return InteractionResultHolder.success(item)
}
areaMode = !areaMode
if (!areaMode) areaModeFirstPos = null
player.displayClientMessage(TextComponent(if (areaMode) "Mode: Area" else "Mode: Single"), true)
save(item)
return InteractionResultHolder.success(item)
} else if (quarry != null) {
val be = level.getBlockEntity(quarry!!)
if (be is QuarryTile) {
val chunk = QuarryChunk(player.blockPosition())
if (areaMode && areaModeFirstPos != null) {
val chunk1 = areaModeFirstPos!!.min(chunk)
val chunk2 = areaModeFirstPos!!.max(chunk)
var chunkCount = 0
for (x in chunk1.x..chunk2.x step 16) for (z in chunk1.z..chunk2.z step 16) {
be.addChunk(QuarryChunk(x, z))
chunkCount++
}
player.displayClientMessage(TextComponent("Added $chunkCount chunks to quarry"), true)
save(item)
return InteractionResultHolder.pass(item)
} else if (areaMode) {
areaModeFirstPos = chunk
player.displayClientMessage(TextComponent("Set first position of area"), true)
save(item)
return InteractionResultHolder.pass(item)
} else {
be.addChunk(chunk)
player.displayClientMessage(TextComponent("Added chunk"), true)
save(item)
return InteractionResultHolder.pass(item)
}
} else {
player.displayClientMessage(TextComponent("Bound quarry is invalid, please rebind"), true)
quarry = null
save(item)
return InteractionResultHolder.fail(item)
}
} else {
player.displayClientMessage(TextComponent("Controller is not bound"), true)
return InteractionResultHolder.fail(item)
}
}
return super.use(level, player, hand)
}
override fun appendHoverText(stack: ItemStack, level: Level?, tooltip: MutableList<Component>, flagIn: TooltipFlag) {
load(stack)
tooltip.add(TextComponent(if (areaMode) "Mode: Area" else "Mode: Single"))
if (areaModeFirstPos != null)
tooltip.add(TextComponent("First chunk: ${areaModeFirstPos!!.x} ${areaModeFirstPos!!.z}"))
if (quarry != null)
tooltip.add(TextComponent("Quarry: ${quarry!!.x}, ${quarry!!.y}, ${quarry!!.z}"))
super.appendHoverText(stack, level, tooltip, flagIn)
}
private fun save(stack: ItemStack) {
val tag = CompoundTag()
tag.putBoolean("area", areaMode)
if (areaModeFirstPos != null)
tag.put("areaFirst", areaModeFirstPos!!.save())
if (quarry != null)
tag.putIntArray("quarry", arrayListOf(quarry!!.x, quarry!!.y, quarry!!.z))
stack.tag = tag
}
private fun load(stack: ItemStack) {
val tag = stack.getOrCreateTag()
if (tag.contains("area"))
areaMode = tag.getBoolean("area")
areaModeFirstPos =
if (tag.contains("areaFirst")) QuarryChunk(tag.getCompound("areaFirst"))
else null
quarry =
if (tag.contains("quarry")) {
val arr = tag.getIntArray("quarry")
BlockPos(arr[0], arr[1], arr[2])
}
else null
}
}

View File

@@ -0,0 +1,49 @@
package de.mattv.quarry
import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.CreativeModeTab
import net.minecraft.world.item.Item
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraftforge.event.RegistryEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.fml.common.Mod
import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.RegistryObject
import thedarkcolour.kotlinforforge.forge.MOD_BUS
import thedarkcolour.kotlinforforge.forge.registerObject
@Mod(QuarryMod.ID)
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
object QuarryMod {
const val ID = "mquarry"
//val LOGGER: Logger = LogManager.getLogger(ID)
val BLOCK_REGISTRY = DeferredRegister.create(ForgeRegistries.BLOCKS, ID)
val TILES_REGISTRY = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITIES, ID)
val ITEM_REGISTRY = DeferredRegister.create(ForgeRegistries.ITEMS, ID)
val QUARRY_BLOCK = BLOCK_REGISTRY.registerObject("quarry", ::QuarryBlock)
val QUARRY_TILE = TILES_REGISTRY.registerObject("quarry") { BlockEntityType.Builder.of(::QuarryTile, QUARRY_BLOCK.get()).build(null) }
val QUARRY_SPEED_UPGRADE = ITEM_REGISTRY.registerObject("upgrade_speed") { QuarryUpgrade(QuarryUpgrade.Type.SPEED) }
val QUARRY_FORTUNE_UPGRADE = ITEM_REGISTRY.registerObject("upgrade_fortune") { QuarryUpgrade(QuarryUpgrade.Type.FORTUNE) }
init {
ITEM_REGISTRY.registerObject("controller", ::QuarryController)
//LOGGER.log(Level.INFO, "MQuarry initializing")
BLOCK_REGISTRY.register(MOD_BUS)
TILES_REGISTRY.register(MOD_BUS)
ITEM_REGISTRY.register(MOD_BUS)
}
@SubscribeEvent
fun onRegisterItems(event: RegistryEvent.Register<Item>) {
for (entry in BLOCK_REGISTRY.entries.stream().map(RegistryObject<Block>::get)) {
val item = BlockItem(entry, Item.Properties().tab(CreativeModeTab.TAB_MISC))
item.setRegistryName(entry.registryName)
event.registry.register(item)
}
}
}

View File

@@ -0,0 +1,276 @@
package de.mattv.quarry
import com.mojang.authlib.GameProfile
import mcjty.theoneprobe.api.IProbeInfo
import net.minecraft.core.BlockPos
import net.minecraft.core.BlockPos.MutableBlockPos
import net.minecraft.core.Direction
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag
import net.minecraft.network.chat.TextComponent
import net.minecraft.network.protocol.Packet
import net.minecraft.network.protocol.game.ClientGamePacketListener
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
import net.minecraft.server.level.ServerLevel
import net.minecraft.util.Tuple
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.enchantment.Enchantments
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.FakePlayer
import net.minecraftforge.common.util.FakePlayerFactory
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.CapabilityEnergy
import net.minecraftforge.energy.IEnergyStorage
import net.minecraftforge.event.world.BlockEvent
import net.minecraftforge.items.CapabilityItemHandler
import net.minecraftforge.items.ItemHandlerHelper
import java.util.*
import kotlin.math.max
import kotlin.math.min
import kotlin.math.pow
import kotlin.streams.asSequence
object FakeQuarryPlayer {
private val profile = GameProfile(UUID.fromString("21a819e9-a98d-4e58-bd52-f60b9570a918"), "[MQuarry]")
fun get(level: ServerLevel): FakePlayer = FakePlayerFactory.get(level, profile)
}
class QuarryTileTicker<T: BlockEntity?> : BlockEntityTicker<T> {
override fun tick(level: Level, pos: BlockPos, state: BlockState, be: T) {
if (level.isClientSide()) return
val tile = be as QuarryTile
tile.tick(level)
}
}
class QuarryTile(private val myPos: BlockPos, state: BlockState) : BlockEntity(QuarryMod.QUARRY_TILE.get(), myPos, state), IEnergyStorage, ICapabilityProvider {
private var energyStored: Int = 0
private var speedLevel: Int = 0
private var fortuneLevel: Int = 0
private var speedUpgradesNeeded: Int = 1
private var fortuneUpgradesNeeded: Int = 1
private var itemsToDrop: MutableList<ItemStack> = ArrayList()
private var curPos: MutableBlockPos = MutableBlockPos(0, myPos.y - 1, 0)
private var curChunk: QuarryChunk? = null
private var chunksTodo: MutableList<QuarryChunk> = ArrayList()
override fun receiveEnergy(maxReceive: Int, simulate: Boolean): Int {
val recv = min(QUARRY_MAX_ENERGY - energyStored, maxReceive)
if (!simulate)
energyStored += recv
return recv
}
override fun extractEnergy(maxExtract: Int, simulate: Boolean): Int {
return 0
}
override fun getEnergyStored(): Int {
return energyStored
}
override fun getMaxEnergyStored(): Int {
return QUARRY_MAX_ENERGY
}
override fun canExtract(): Boolean {
return false
}
override fun canReceive(): Boolean {
return true
}
override fun <T: Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (cap == CapabilityEnergy.ENERGY) return LazyOptional.of { this as T }
return super<BlockEntity>.getCapability(cap, side)
}
private fun getPickaxe(): ItemStack = Items.NETHERITE_PICKAXE.defaultInstance.apply {
if (fortuneLevel > 0) enchant(Enchantments.BLOCK_FORTUNE, fortuneLevel)
}
private fun breakBlock(level: Level, pos: BlockPos): Boolean {
val state = level.getBlockState(pos)
val pickaxe = getPickaxe()
val player = FakeQuarryPlayer.get(level as ServerLevel)
player.setItemInHand(InteractionHand.MAIN_HAND, pickaxe)
val event = BlockEvent.BreakEvent(level, pos, state, player)
MinecraftForge.EVENT_BUS.post(event)
if (event.isCanceled) return true
if (state.isAir) return true
if (state.getDestroySpeed(level, pos) < 0) return true
val energyNeeded = ENERGY_BASE + max(0, (state.getDestroySpeed(level, pos) * ENERGY_PER_STRENGTH).toInt())
if (energyStored < energyNeeded) return false
energyStored -= energyNeeded
if (level.getFluidState(pos).isEmpty) // Is not a liquid
itemsToDrop.addAll(Block.getDrops(state, level, pos, level.getBlockEntity(pos), player, pickaxe))
level.setBlock(pos, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL)
setChanged()
return true
}
private fun newChunk() {
curChunk = chunksTodo.removeFirstOrNull()
}
fun tick(level: Level) {
// Mine
if (curChunk == null) newChunk()
if (itemsToDrop.isEmpty() && curChunk != null) {
var curChunkPos = curChunk!!.asPos()
for (i in 0..speedLevel) {
if (!breakBlock(level, curChunkPos.offset(curPos))) break
curPos.x++
if (curPos.x == 16) {
curPos.x = 0
curPos.z++
}
if (curPos.z == 16) {
curPos.z = 0
curPos.y--
}
if (curPos.y == level.minBuildHeight - 1) {
curPos.y = myPos.y - 1
newChunk()
if (curChunk == null) break
curChunkPos = curChunk!!.asPos()
}
}
}
if (itemsToDrop.isEmpty()) return
// Drop items
val te = level.getBlockEntity(myPos.offset(0, 1, 0)) ?: return
val itemHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.DOWN).orElse(null) ?: return
val newDrops = ArrayList<ItemStack>()
for (drop in itemsToDrop) {
val newDrop = ItemHandlerHelper.insertItemStacked(itemHandler, drop, false)
if (!newDrop.isEmpty) newDrops.add(newDrop)
}
itemsToDrop = newDrops
setChanged()
}
fun playerInfo(): String = "Speed: $speedLevel, needed: $speedUpgradesNeeded | Fortune: $fortuneLevel, needed: $fortuneUpgradesNeeded | " + if (curChunk != null) "Chunks in queue: ${chunksTodo.size}" else "Idle"
fun useUpgrade(player: Player, stack: ItemStack) {
val item = stack.item as QuarryUpgrade
if (item.ty == QuarryUpgrade.Type.SPEED) {
val used = min(stack.count, speedUpgradesNeeded)
stack.shrink(used)
speedUpgradesNeeded -= used
if (speedUpgradesNeeded == 0) {
speedLevel++
speedUpgradesNeeded = (2.0).pow(speedLevel).toInt()
player.displayClientMessage(TextComponent("New speed level: $speedLevel, upgrades needed for next level: $speedUpgradesNeeded"), true)
} else
player.displayClientMessage(TextComponent("Upgrades needed for next level: $speedUpgradesNeeded"), true)
} else {
val used = min(stack.count, fortuneUpgradesNeeded)
stack.shrink(used)
fortuneUpgradesNeeded -= used
if (fortuneUpgradesNeeded == 0) {
fortuneLevel++
fortuneUpgradesNeeded = (2.0).pow(fortuneLevel).toInt()
player.displayClientMessage(TextComponent("New fortune level: $fortuneLevel, upgrades needed for next level: $fortuneUpgradesNeeded"), true)
} else
player.displayClientMessage(TextComponent("Upgrades needed for next level: $fortuneUpgradesNeeded"), true)
}
}
fun getUpgradesToDrop() : Tuple<Int, Int> {
var speed = (2.0).pow(speedLevel).toInt() - speedUpgradesNeeded
for (i in 1..speedLevel) speed += (2.0).pow(i-1).toInt()
var fortune = (2.0).pow(fortuneLevel).toInt() - fortuneUpgradesNeeded
for (i in 1..fortuneLevel) fortune += (2.0).pow(i-1).toInt()
return Tuple(speed, fortune)
}
fun addChunk(chunk: QuarryChunk) = chunksTodo.add(chunk)
private fun saveClientData(tag: CompoundTag) {
tag.putInt("energy", energyStored)
tag.putInt("speedLevel", speedLevel)
tag.putInt("fortuneLevel", fortuneLevel)
tag.putInt("speedUpgradesNeeded", speedUpgradesNeeded)
tag.putInt("fortuneUpgradesNeeded", fortuneUpgradesNeeded)
}
override fun saveAdditional(tag: CompoundTag) {
saveClientData(tag)
val dropsList = ListTag()
itemsToDrop.stream().forEach {
val itemTag = CompoundTag()
it.save(itemTag)
dropsList.add(itemTag)
}
tag.put("drops", dropsList)
tag.putInt("curPosX", curPos.x)
tag.putInt("curPosY", curPos.y)
tag.putInt("curPosZ", curPos.z)
if (curChunk != null) {
tag.put("curChunk", curChunk!!.save())
}
val chunkList = ListTag()
chunkList.addAll(chunksTodo.stream().map(QuarryChunk::save).asSequence())
tag.put("chunks", chunkList)
}
override fun load(tag: CompoundTag) {
energyStored = tag.getInt("energy")
speedLevel = tag.getInt("speedLevel")
fortuneLevel = tag.getInt("fortuneLevel")
speedUpgradesNeeded = tag.getInt("speedUpgradesNeeded")
fortuneUpgradesNeeded = tag.getInt("fortuneUpgradesNeeded")
if (!tag.contains("drops")) return // Everything after this is server only
itemsToDrop = tag.getList("drops", Tag.TAG_COMPOUND.toInt())
.map { ItemStack.of(it as CompoundTag) }.toMutableList()
curPos.x = tag.getInt("curPosX")
curPos.y = tag.getInt("curPosY")
curPos.z = tag.getInt("curPosZ")
curChunk = if (tag.contains("curChunk")) QuarryChunk(tag.get("curChunk") as CompoundTag) else null
chunksTodo = tag.getList("chunks", CompoundTag.TAG_COMPOUND.toInt())
.map { QuarryChunk(it as CompoundTag) }.toMutableList()
}
override fun getUpdateTag(): CompoundTag {
val tag = CompoundTag()
saveClientData(tag)
return tag
}
override fun getUpdatePacket(): Packet<ClientGamePacketListener>? = ClientboundBlockEntityDataPacket.create(this)
fun probeInfo(info: IProbeInfo) {
val speedMax = (2.0).pow(speedLevel).toInt()
info.text("Speed: level $speedLevel, ${speedMax - speedUpgradesNeeded}/$speedMax")
val fortuneMax = (2.0).pow(fortuneLevel).toInt()
info.text("Fortune: level $fortuneLevel, ${fortuneMax - fortuneUpgradesNeeded}/$fortuneMax")
if (itemsToDrop.isNotEmpty())
info.text("Waiting to extract items...")
else if (curChunk != null) {
val pos = curChunk!!.asPos().offset(curPos)
info.text("Currently mining: ${pos.x} ${pos.y} ${pos.z}")
info.text("Chunks in queue: ${chunksTodo.size}")
} else info.text("Idle")
}
companion object {
const val QUARRY_MAX_ENERGY: Int = 100_000_000
const val ENERGY_BASE = 1000
const val ENERGY_PER_STRENGTH = 500
}
}

View File

@@ -0,0 +1,20 @@
package de.mattv.quarry
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.item.CreativeModeTab
import net.minecraft.world.item.Item
import net.minecraft.world.item.context.UseOnContext
class QuarryUpgrade(val ty: Type) : Item(Properties().tab(CreativeModeTab.TAB_MISC)) {
enum class Type { SPEED, FORTUNE }
override fun useOn(ctx: UseOnContext): InteractionResult {
val be = ctx.level.getBlockEntity(ctx.clickedPos)
if (!ctx.level.isClientSide() && ctx.hand == InteractionHand.MAIN_HAND && be is QuarryTile) {
be.useUpgrade(ctx.player!!, ctx.itemInHand)
return InteractionResult.CONSUME
}
return super.useOn(ctx)
}
}

View File

@@ -0,0 +1,58 @@
# This is an example mods.toml file. It contains the data relating to the loading mods.
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
# The overall format is standard TOML format, v0.5.0.
# Note that there are a couple of TOML lists in this file.
# Find more information on toml format here: https://github.com/toml-lang/toml
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
modLoader="kotlinforforge" #mandatory
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
loaderVersion="[3,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
license="GNU GPL 3.0"
# A URL to refer people to when problems occur with this mod
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
# A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
# The modid of the mod
modId="mquarry" #mandatory
# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
# see the associated build.gradle script for how to populate this completely automatically during a build
version="${file.jarVersion}" #mandatory
# A display name for the mod
displayName="MQuarry" #mandatory
# A URL to query for updates for this mod. See the JSON update specification https://docs.minecraftforge.net/en/latest/misc/updatechecker/
#updateJSONURL="https://change.me.example.invalid/updates.json" #optional
# A URL for the "homepage" for this mod, displayed in the mod UI
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
# A file name (in the root of the mod JAR) containing a logo for display
#logoFile="mattv.png" #optional
# A text field displayed in the mod UI
#credits="Thanks for this example mod goes to Java" #optional
# A text field displayed in the mod UI
#authors="Love, Cheese and small house plants" #optional
# The description text for the mod (multi line!) (#mandatory)
description='''
'''
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
[[dependencies.mquarry]] #optional
# the modid of the dependency
modId="forge" #mandatory
# Does this dependency have to exist - if not, ordering below must be specified
mandatory=true #mandatory
# The version range of the dependency
versionRange="[40,)" #mandatory
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
ordering="NONE"
# Side this dependency is applied on - BOTH, CLIENT or SERVER
side="BOTH"
# Here's another dependency
[[dependencies.mquarry]]
modId="minecraft"
mandatory=true
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange="[1.18.2,1.19)"
ordering="NONE"
side="BOTH"

View File

@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "mquarry:block/quarry"
}
}
}

View File

@@ -0,0 +1,7 @@
{
"block.mquarry.quarry": "MQuarry",
"item.mquarry.upgrade_speed": "MQuarry speed upgrade",
"item.mquarry.upgrade_fortune": "MQuarry fortune upgrade",
"item.mquarry.controller": "MQuarry controller"
}

View File

@@ -0,0 +1,11 @@
{
"parent": "block/cube_all",
"textures": {
"up": "mquarry:blocks/quarry/updown",
"down": "mquarry:blocks/quarry/updown",
"north": "mquarry:blocks/quarry/side",
"south": "mquarry:blocks/quarry/side",
"west": "mquarry:blocks/quarry/side",
"east": "mquarry:blocks/quarry/side"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "mquarry:items/controller"
}
}

View File

@@ -0,0 +1,3 @@
{
"parent": "mquarry:block/quarry"
}

View File

@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "mquarry:items/upgrade_fortune"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "mquarry:items/upgrade_speed"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

View File

@@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"mquarry:quarry"
]
}

View File

@@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"mquarry:quarry"
]
}

View File

@@ -0,0 +1,14 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1.0,
"entries": [
{
"type": "minecraft:item",
"name": "mquarry:quarry"
}
]
}
]
}

View File

@@ -0,0 +1,8 @@
{
"pack": {
"description": "mquarry resources",
"pack_format": 8
,"forge:resource_pack_format": 8
,"forge:data_pack_format": 9
}
}