diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/BreakableContainerBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/BreakableContainerBlock.kt new file mode 100644 index 000000000..dd68686cf --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/BreakableContainerBlock.kt @@ -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 { + val entity = params.getOptionalParameter(LootContextParams.BLOCK_ENTITY) + + if (entity is BreakableContainerBlockEntity) + return entity.loot.getItems(params, state) + + return super.getDrops(state, params) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/BreakableContainerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/BreakableContainerBlockEntity.kt new file mode 100644 index 000000000..d5dfd0d08 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/BreakableContainerBlockEntity.kt @@ -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) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/BlockLootTableHolder.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/BlockLootTableHolder.kt new file mode 100644 index 000000000..eda7f3e01 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/BlockLootTableHolder.kt @@ -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? = 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 { + return lookup(level).getRandomItems(params, selectRandom(overrideSeed, level.otmRandom)) + } + + fun getItems(params: LootParams.Builder, blockState: BlockState, overrideSeed: Long? = null): MutableList { + val level = params.level + val create = params.withParameter(LootContextParams.BLOCK_STATE, blockState).create(LootContextParamSets.BLOCK) + return getItems(create, level, overrideSeed) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt index 03e4d3d46..c3ebab17d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt @@ -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 { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlockEntities.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlockEntities.kt index 021700c52..b5f8e80df 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlockEntities.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlockEntities.kt @@ -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 by registry.register(MNames.HOLO_SIGN) { BlockEntityType.Builder.of(::HoloSignBlockEntity, MBlocks.HOLO_SIGN).build(null) } + val BREAKABLE: BlockEntityType by registry.register("breakable") { + val blocks = ArrayList() + 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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlocks.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlocks.kt index 33d27ca12..8a4558eae 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlocks.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MBlocks.kt @@ -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) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MItems.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MItems.kt index 622cf8a9e..e287a6d0d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/game/MItems.kt @@ -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) }