Loot tables for cargo crates?

This commit is contained in:
DBotThePony 2022-10-08 17:35:07 +07:00
parent c0364736f4
commit 75ffae542d
Signed by: DBot
GPG Key ID: DCC23B5715498507
3 changed files with 87 additions and 14 deletions

View File

@ -32,10 +32,12 @@ class CargoCrateBlock(val color: DyeColor?) : RotatableMatteryBlock(
return super.getStateForPlacement(context)?.setValue(IS_OPEN, false)
}
@Suppress("OVERRIDE_DEPRECATION")
override fun hasAnalogOutputSignal(p_60457_: BlockState): Boolean {
return true
}
@Suppress("OVERRIDE_DEPRECATION")
override fun getAnalogOutputSignal(p_60487_: BlockState, level: Level, p_60489_: BlockPos): Int {
val tile = level.getBlockEntity(p_60489_) as? CargoCrateBlockEntity ?: return 0
return AbstractContainerMenu.getRedstoneSignalFromContainer(tile.container)

View File

@ -1,28 +1,41 @@
package ru.dbotthepony.mc.otm.block.entity
import net.minecraft.advancements.CriteriaTriggers
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.LongTag
import net.minecraft.nbt.StringTag
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
import net.minecraft.world.Container
import net.minecraft.world.Containers
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.gameevent.GameEvent
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.phys.Vec3
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.CargoCrateBlock
import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerFilter
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.menu.CargoCrateMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.registry.MSoundEvents
class CargoCrateBlockEntity(
@ -31,7 +44,18 @@ class CargoCrateBlockEntity(
) : MatteryBlockEntity(MBlockEntities.CARGO_CRATE, p_155229_, p_155230_), IDroppableContainer {
val container = MatteryContainer(this::setChanged, CAPACITY)
private var interactingPlayers = 0
val handler = container.handler()
val handler = container.handler(object : MatteryContainerFilter {
override fun preInsert(slot: Int, stack: ItemStack, simulate: Boolean) {
unpackLootTable()
}
override fun preExtract(slot: Int, amount: Int, simulate: Boolean) {
unpackLootTable()
}
})
var lootTable: ResourceLocation? = null
var lootTableSeed: Long? = null
override val droppableContainer: Container
get() = container
@ -72,20 +96,56 @@ class CargoCrateBlockEntity(
return super.getCapability(cap, side)
}
public override fun saveAdditional(nbt: CompoundTag) {
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
lootTable?.let { nbt[LOOT_TABLE_KEY] = it.toString() }
lootTableSeed?.let { nbt[LOOT_TABLE_SEED_KEY] = it }
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
container.deserializeNBT(nbt[INVENTORY_KEY])
lootTable = nbt.map(LOOT_TABLE_KEY) { it: StringTag -> ResourceLocation.tryParse(it.asString) }
lootTableSeed = (nbt[LOOT_TABLE_SEED_KEY] as LongTag?)?.asLong
}
fun unpackLootTable(ply: Player? = null) {
val lootTable = lootTable ?: return
val lootTableSeed = lootTableSeed ?: 0L
val server = level?.server ?: return
val loot = server.lootTables.get(lootTable)
if (ply is ServerPlayer) {
CriteriaTriggers.GENERATE_LOOT.trigger(ply, lootTable)
}
this.lootTable = null
this.lootTableSeed = null
val context = LootContext.Builder(level as ServerLevel)
.withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(this.worldPosition))
.withOptionalRandomSeed(lootTableSeed)
if (ply != null) {
context.withLuck(ply.luck).withParameter(LootContextParams.THIS_ENTITY, ply)
}
Containers.dropContents(level as ServerLevel, blockPos, container)
loot.fill(container, context.create(LootContextParamSets.CHEST))
}
override val defaultDisplayName: Component
get() = MACHINE_NAME
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
if (lootTable != null && ply.isSpectator)
return null
unpackLootTable(ply)
return CargoCrateMenu(containerID, inventory, this)
}

View File

@ -5,8 +5,16 @@ import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.IItemHandler
interface MatteryContainerFilter {
fun canInsert(slot: Int, stack: ItemStack): Boolean
fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean
fun canInsert(slot: Int, stack: ItemStack): Boolean {
return true
}
fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
return true
}
fun preInsert(slot: Int, stack: ItemStack, simulate: Boolean) {}
fun preExtract(slot: Int, amount: Int, simulate: Boolean) {}
}
object MatteryContainerFilterOnlyIn : MatteryContainerFilter {
@ -41,7 +49,7 @@ object MatteryContainerFilterBoth : MatteryContainerFilter {
class MatteryContainerHandler @JvmOverloads internal constructor(
private val container: MatteryContainer,
private val filter: MatteryContainerFilter = MatteryContainerFilterBoth,
private val hooks: MatteryContainerFilter = MatteryContainerFilterBoth,
) : IItemHandler {
private var handler = LazyOptional.of<IItemHandler> { this }
@ -61,9 +69,10 @@ class MatteryContainerHandler @JvmOverloads internal constructor(
override fun getStackInSlot(slot: Int) = container[slot]
override fun insertItem(slot: Int, stack: ItemStack, simulate: Boolean): ItemStack {
if (!filter.canInsert(slot, stack))
if (!hooks.canInsert(slot, stack))
return stack
hooks.preInsert(slot, stack, simulate)
val localStack = container[slot]
if (localStack.isEmpty) {
@ -100,9 +109,11 @@ class MatteryContainerHandler @JvmOverloads internal constructor(
require(amount >= 0) { "Can not extract negative amount of items" }
hooks.preExtract(slot, amount, simulate)
val localStack = container.getItem(slot)
if (localStack.isEmpty) return ItemStack.EMPTY
if (!filter.canExtract(slot, amount, localStack)) return ItemStack.EMPTY
if (!hooks.canExtract(slot, amount, localStack)) return ItemStack.EMPTY
val minimal = Math.min(amount, localStack.count)
val copy = localStack.copy()
@ -122,6 +133,6 @@ class MatteryContainerHandler @JvmOverloads internal constructor(
}
override fun isItemValid(slot: Int, stack: ItemStack): Boolean {
return filter.canInsert(slot, stack)
return hooks.canInsert(slot, stack)
}
}