Proof-of-concept "Small capsule" loot block

This commit is contained in:
DBotThePony 2025-03-22 23:33:28 +07:00
parent 22ebdbb1eb
commit c778f192b2
Signed by: DBot
GPG Key ID: DCC23B5715498507
7 changed files with 157 additions and 0 deletions

View File

@ -0,0 +1,26 @@
package ru.dbotthepony.mc.otm.block.decorative
import net.minecraft.core.BlockPos
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.storage.loot.LootParams
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.decorative.BreakableContainerBlockEntity
class BreakableContainerBlock(properties: Properties) : RotatableMatteryBlock(properties), EntityBlock {
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
return BreakableContainerBlockEntity(pos, state)
}
override fun getDrops(state: BlockState, params: LootParams.Builder): MutableList<ItemStack> {
val entity = params.getOptionalParameter(LootContextParams.BLOCK_ENTITY)
if (entity is BreakableContainerBlockEntity)
return entity.loot.getItems(params, state)
return super.getDrops(state, params)
}
}

View File

@ -0,0 +1,23 @@
package ru.dbotthepony.mc.otm.block.entity.decorative
import net.minecraft.core.BlockPos
import net.minecraft.core.HolderLookup
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.core.util.BlockLootTableHolder
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
class BreakableContainerBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.BREAKABLE, blockPos, blockState) {
val loot = BlockLootTableHolder(::markDirtyFast)
override fun saveLevel(nbt: CompoundTag, registry: HolderLookup.Provider) {
super.saveLevel(nbt, registry)
loot.save(nbt, registry)
}
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
super.loadAdditional(nbt, registry)
loot.load(nbt, registry)
}
}

View File

@ -0,0 +1,87 @@
package ru.dbotthepony.mc.otm.core.util
import net.minecraft.core.HolderLookup
import net.minecraft.core.registries.Registries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.util.RandomSource
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.storage.loot.LootParams
import net.minecraft.world.level.storage.loot.LootTable
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.LOOT_TABLE_KEY
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.LOOT_TABLE_SEED_KEY
import ru.dbotthepony.mc.otm.core.otmRandom
class BlockLootTableHolder(private val listener: Runnable = Runnable { }) {
private var ignoreListener = false
var lootTable: ResourceKey<LootTable>? = null
set(value) {
if (field != value) {
field = value
if (!ignoreListener) listener.run()
}
}
var lootTableSeed: Long? = null
set(value) {
if (field != value) {
field = value
if (!ignoreListener) listener.run()
}
}
fun save(nbt: CompoundTag, registry: HolderLookup.Provider) {
try {
ignoreListener = true
if (lootTable != null) {
nbt.putString(LOOT_TABLE_KEY, lootTable!!.location().toString())
if (lootTableSeed != null)
nbt.putLong(LOOT_TABLE_SEED_KEY, lootTableSeed!!)
}
} finally {
ignoreListener = false
}
}
fun load(nbt: CompoundTag, registry: HolderLookup.Provider) {
try {
ignoreListener = true
if (nbt.contains(LOOT_TABLE_KEY, Tag.TAG_STRING.toInt())) {
lootTable = ResourceLocation.tryParse(nbt.getString(LOOT_TABLE_KEY))?.let { ResourceKey.create(Registries.LOOT_TABLE, it) }
lootTableSeed = if (nbt.contains(LOOT_TABLE_SEED_KEY, Tag.TAG_LONG.toInt())) nbt.getLong(LOOT_TABLE_SEED_KEY) else null
}
} finally {
ignoreListener = false
}
}
fun lookup(level: ServerLevel): LootTable {
val lootTable = lootTable ?: return LootTable.EMPTY
return level.server.reloadableRegistries().getLootTable(lootTable)
}
private fun selectRandom(overrideSeed: Long?, fallback: RandomSource): RandomSource {
val lootTableSeed = overrideSeed ?: lootTableSeed
return if (lootTableSeed == null) fallback else GJRAND64RandomSource(lootTableSeed)
}
fun getItems(params: LootParams, level: ServerLevel, overrideSeed: Long? = null): MutableList<ItemStack> {
return lookup(level).getRandomItems(params, selectRandom(overrideSeed, level.otmRandom))
}
fun getItems(params: LootParams.Builder, blockState: BlockState, overrideSeed: Long? = null): MutableList<ItemStack> {
val level = params.level
val create = params.withParameter(LootContextParams.BLOCK_STATE, blockState).create(LootContextParamSets.BLOCK)
return getItems(create, level, overrideSeed)
}
}

View File

@ -341,6 +341,8 @@ object MNames {
const val TRITANIUM_DOOR = "tritanium_door"
const val TRITANIUM_TRAPDOOR = "tritanium_trapdoor"
const val TRITANIUM_PRESSURE_PLATE = "tritanium_pressure_plate"
const val SMALL_CAPSULE = "small_capsule"
}
object StatNames {

View File

@ -12,6 +12,7 @@ import ru.dbotthepony.mc.otm.block.entity.tech.*
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleGeneratorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.cable.SimpleEnergyCableBlockEntity
import ru.dbotthepony.mc.otm.block.entity.decorative.BreakableContainerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
import ru.dbotthepony.mc.otm.block.entity.decorative.DevChestBlockEntity
import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity
@ -118,6 +119,12 @@ object MBlockEntities {
val HOLO_SIGN: BlockEntityType<HoloSignBlockEntity> by registry.register(MNames.HOLO_SIGN) { BlockEntityType.Builder.of(::HoloSignBlockEntity, MBlocks.HOLO_SIGN).build(null) }
val BREAKABLE: BlockEntityType<BreakableContainerBlockEntity> by registry.register("breakable") {
val blocks = ArrayList<Block>()
blocks.add(MBlocks.SMALL_CAPSULE)
BlockEntityType.Builder.of(::BreakableContainerBlockEntity, *blocks.toTypedArray()).build(null)
}
internal fun register(bus: IEventBus) {
registry.register(bus)
bus.addListener(this::registerClient)

View File

@ -37,6 +37,7 @@ import ru.dbotthepony.mc.otm.block.MultiblockTestBlock
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.StorageCableBlock
import ru.dbotthepony.mc.otm.block.addSimpleDescription
import ru.dbotthepony.mc.otm.block.decorative.BreakableContainerBlock
import ru.dbotthepony.mc.otm.block.decorative.DevChestBlock
import ru.dbotthepony.mc.otm.block.decorative.EngineBlock
import ru.dbotthepony.mc.otm.block.decorative.FluidTankBlock
@ -434,6 +435,15 @@ object MBlocks {
val MULTIBLOCK_TEST by registry.register("multiblock_test") { MultiblockTestBlock() }
val SMALL_CAPSULE by registry.register(MNames.SMALL_CAPSULE) {
BreakableContainerBlock(
BlockBehaviour.Properties.of()
.mapColor(MapColor.COLOR_GRAY)
.destroyTime(0f)
.explosionResistance(1.5f)
)
}
init {
MRegistry.registerBlocks(registry)
}

View File

@ -680,6 +680,8 @@ object MItems {
val CONFIGURATOR: Item by registry.register(MNames.CONFIGURATOR) { ConfiguratorItem() }
val SMALL_CAPSULE by registry.register(MNames.SMALL_CAPSULE) { BlockItem(MBlocks.SMALL_CAPSULE, DEFAULT_PROPERTIES) }
init {
MRegistry.registerItems(registry)
}