Create separate loot item function for saving tile nbt data

This commit is contained in:
DBotThePony 2023-02-23 15:11:45 +07:00
parent 5b12be2ac4
commit a9b28a66ca
Signed by: DBot
GPG Key ID: DCC23B5715498507
7 changed files with 135 additions and 150 deletions

View File

@ -24,11 +24,11 @@ import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition
import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.core.stream
import ru.dbotthepony.mc.otm.data.loot.CopyTileNbtFunction
data class NbtCopy(val source: String, val destination: String, val strategy: CopyNbtFunction.MergeStrategy = CopyNbtFunction.MergeStrategy.REPLACE)
@ -155,91 +155,11 @@ class LootTables(generator: DataGenerator) : LootTableProvider(generator.packOut
}
}
fun tile(block: Block, f: (CopyNbtFunction.Builder) -> Unit = {}) {
fun tile(block: Block, vararg filterTags: String) {
singleLootPool(LootContextParamSets.BLOCK, block.lootTable) {
add(LootItem.lootTableItem(block).also {
it.apply(CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY).also {
it.copy("Name", "BlockEntityTag.Name")
f(it)
})
it.apply(CopyTileNbtFunction(filterTags.stream()))
})
}
}
fun tile(block: Block, vararg tags: NbtCopy) {
tile(block) {
for ((source, destination, strategy) in tags) {
it.copy(source, destination, strategy)
}
}
}
fun basicTile(block: Block, vararg tags: NbtCopy) {
tile(block) {
for ((source, destination, strategy) in tags) {
it.copy(source, destination, strategy)
}
for ((source, destination, strategy) in basicTags) {
it.copy(source, destination, strategy)
}
}
}
fun poweredTile(block: Block, vararg tags: NbtCopy) {
tile(block) {
for ((source, destination, strategy) in tags) {
it.copy(source, destination, strategy)
}
for ((source, destination, strategy) in poweredTags) {
it.copy(source, destination, strategy)
}
}
}
fun workerTile(block: Block, vararg tags: NbtCopy) {
tile(block) {
for ((source, destination, strategy) in tags) {
it.copy(source, destination, strategy)
}
for ((source, destination, strategy) in workerTags) {
it.copy(source, destination, strategy)
}
}
}
fun matterWorkerTile(block: Block, vararg tags: NbtCopy) {
tile(block) {
for ((source, destination, strategy) in tags) {
it.copy(source, destination, strategy)
}
for ((source, destination, strategy) in poweredMatterWorker) {
it.copy(source, destination, strategy)
}
}
}
fun tile(block: Block, vararg tags: String) {
tile(block, *tags.map { NbtCopy(it, "BlockEntityTag.$it", CopyNbtFunction.MergeStrategy.REPLACE) }.toTypedArray())
}
// fix overload resolution by adding extra required argument
fun basicTile(block: Block, f: String, vararg tags: String) {
basicTile(block, *tags.map { TileNbtCopy(it) }.toMutableList().also { it.add(TileNbtCopy(f)) }.toTypedArray())
}
fun poweredTile(block: Block, f: String, vararg tags: String) {
poweredTile(block, *tags.map { TileNbtCopy(it) }.toMutableList().also { it.add(TileNbtCopy(f)) }.toTypedArray())
}
fun workerTile(block: Block, f: String, vararg tags: String) {
workerTile(block, *tags.map { TileNbtCopy(it) }.toMutableList().also { it.add(TileNbtCopy(f)) }.toTypedArray())
}
fun matterWorkerTile(block: Block, f: String, vararg tags: String) {
matterWorkerTile(block, *tags.map { TileNbtCopy(it) }.toMutableList().also { it.add(TileNbtCopy(f)) }.toTypedArray())
}
}

View File

@ -58,8 +58,6 @@ fun addLootTables(lootTables: LootTables) {
lootTables.dropsSelf(MBlocks.METAL_BEAM) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.TRITANIUM_INGOT_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.tile(MBlocks.COBBLESTONE_GENERATOR)
lootTables.dropsSelf(MBlocks.ENGINE) { condition(ExplosionCondition.survivesExplosion()) }
for (door in MBlocks.TRITANIUM_TRAPDOOR.values)
@ -133,41 +131,31 @@ fun addLootTables(lootTables: LootTables) {
lootPool { item(Items.BLACK_DYE) { setCount(64) } }
}
lootTables.tile(MBlocks.COBBLESTONE_GENERATOR)
lootTables.tile(MBlocks.ENERGY_SERVO)
lootTables.tile(MBlocks.ENERGY_COUNTER)
lootTables.tile(MBlocks.CHEMICAL_GENERATOR)
lootTables.tile(MBlocks.HOLO_SIGN)
lootTables.tile(MBlocks.STORAGE_CABLE)
lootTables.tile(MBlocks.ANDROID_STATION)
lootTables.tile(MBlocks.BATTERY_BANK)
lootTables.tile(MBlocks.DRIVE_VIEWER)
lootTables.tile(MBlocks.ENERGY_COUNTER,
EnergyCounterBlockEntity.IO_LIMIT_KEY, EnergyCounterBlockEntity.PASSED_ENERGY_KEY,
EnergyCounterBlockEntity.POWER_HISTORY_KEY, EnergyCounterBlockEntity.POWER_HISTORY_POINTER_KEY)
lootTables.tile(MBlocks.STORAGE_BUS)
lootTables.tile(MBlocks.STORAGE_IMPORTER)
lootTables.tile(MBlocks.STORAGE_EXPORTER)
lootTables.tile(MBlocks.STORAGE_POWER_SUPPLIER)
lootTables.tile(MBlocks.DRIVE_RACK)
lootTables.tile(MBlocks.CHEMICAL_GENERATOR,
ChemicalGeneratorBlockEntity.WORK_TICKS_KEY,
ChemicalGeneratorBlockEntity.WORK_TICKS_TOTAL_KEY,
ENERGY_KEY,
REDSTONE_CONTROL_KEY,
)
lootTables.tile(MBlocks.MATTER_DECOMPOSER)
lootTables.tile(MBlocks.MATTER_REPLICATOR)
lootTables.tile(MBlocks.MATTER_RECYCLER)
lootTables.tile(MBlocks.MATTER_SCANNER)
lootTables.tile(MBlocks.PLATE_PRESS)
lootTables.tile(MBlocks.HOLO_SIGN, HoloSignBlockEntity.TEXT_KEY, HoloSignBlockEntity.REDSTONE_CONTROL_KEY)
lootTables.dropsSelf(MBlocks.STORAGE_CABLE)
lootTables.poweredTile(MBlocks.ANDROID_STATION)
lootTables.basicTile(MBlocks.BATTERY_BANK)
lootTables.poweredTile(MBlocks.DRIVE_VIEWER)
lootTables.poweredTile(MBlocks.STORAGE_BUS, TileNbtCopy(FILTER_KEY))
lootTables.poweredTile(MBlocks.STORAGE_IMPORTER, TileNbtCopy(FILTER_KEY))
lootTables.poweredTile(MBlocks.STORAGE_EXPORTER, TileNbtCopy(FILTER_KEY))
lootTables.poweredTile(MBlocks.STORAGE_POWER_SUPPLIER, TileNbtCopy(StoragePowerSupplierBlockEntity.POWER_PASSED_KEY))
lootTables.poweredTile(MBlocks.DRIVE_RACK)
lootTables.matterWorkerTile(MBlocks.MATTER_DECOMPOSER)
lootTables.matterWorkerTile(MBlocks.MATTER_REPLICATOR)
lootTables.matterWorkerTile(MBlocks.MATTER_RECYCLER)
lootTables.workerTile(MBlocks.MATTER_SCANNER)
lootTables.workerTile(MBlocks.PLATE_PRESS)
lootTables.basicTile(MBlocks.MATTER_PANEL, TileNbtCopy("tasks"))
lootTables.basicTile(MBlocks.PATTERN_STORAGE)
lootTables.basicTile(MBlocks.MATTER_CAPACITOR_BANK)
lootTables.poweredTile(MBlocks.MATTER_BOTTLER,
TileNbtCopy(MATTER_STORAGE_KEY), TileNbtCopy(MatterBottlerBlockEntity.IS_BOTTLING_KEY))
lootTables.tile(MBlocks.MATTER_PANEL)
lootTables.tile(MBlocks.PATTERN_STORAGE)
lootTables.tile(MBlocks.MATTER_CAPACITOR_BANK)
lootTables.tile(MBlocks.MATTER_BOTTLER)
}

View File

@ -192,7 +192,7 @@ abstract class MatteryBlock @JvmOverloads constructor(
newBlockState: BlockState,
movedByPiston: Boolean
) {
if (!oldBlockState.`is`(newBlockState.block)) {
if (!oldBlockState.`is`(newBlockState.block) && !level.isClientSide) {
val blockentity = level.getBlockEntity(blockPos)
if (blockentity is MatteryBlockEntity) {

View File

@ -221,8 +221,27 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
val bottomDefault: ItemHandlerMode = determineDefaultMode(input, output, battery, RelativeSide.BOTTOM),
) {
val sideless: IItemHandler
val possibleViews: ImmutableSet<ItemHandlerMode>
val inputOutput: IItemHandler?
init {
val builder = ImmutableSet.Builder<ItemHandlerMode>()
builder.add(ItemHandlerMode.DISABLED)
if (input != null) builder.add(ItemHandlerMode.INPUT)
if (output != null) builder.add(ItemHandlerMode.OUTPUT)
if (input != null && output != null) builder.add(ItemHandlerMode.INPUT_OUTPUT)
if (battery != null) builder.add(ItemHandlerMode.BATTERY)
possibleViews = builder.build()
if (input != null && output != null) {
inputOutput = CombinedItemHandler(input, output)
} else {
inputOutput = null
}
val caps = ArrayList<IItemHandler>()
if (input != null) caps.add(input)
@ -258,28 +277,6 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
put(RelativeSide.BOTTOM, bottomDefault)
}
val possibleViews: ImmutableSet<ItemHandlerMode>
val inputOutput: IItemHandler?
init {
val builder = ImmutableSet.Builder<ItemHandlerMode>()
builder.add(ItemHandlerMode.DISABLED)
if (input != null) builder.add(ItemHandlerMode.INPUT)
if (output != null) builder.add(ItemHandlerMode.OUTPUT)
if (input != null && output != null) builder.add(ItemHandlerMode.INPUT_OUTPUT)
if (battery != null) builder.add(ItemHandlerMode.BATTERY)
possibleViews = builder.build()
if (input != null && output != null) {
inputOutput = CombinedItemHandler(input, output)
} else {
inputOutput = null
}
}
inner class Piece(
val side: RelativeSide,
) : IItemHandler, ITickable {

View File

@ -0,0 +1,77 @@
package ru.dbotthepony.mc.otm.data.loot
import com.google.common.collect.ImmutableList
import com.google.gson.JsonArray
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.Serializer
import net.minecraft.world.level.storage.loot.functions.LootItemFunction
import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.stream
import ru.dbotthepony.mc.otm.core.tagNotNull
import ru.dbotthepony.mc.otm.data.stream
import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes
import java.util.stream.Stream
class CopyTileNbtFunction(filter: Stream<out String> = Stream.empty()) : LootItemFunction, LootItemFunction.Builder {
constructor(filter: Collection<String>) : this(filter.stream())
constructor(vararg filter: String) : this(filter.stream())
val filter: ImmutableList<String> = /*immutableList {
filter.forEach(this)
}*/ filter.collect(ImmutableList.toImmutableList())
override fun apply(t: ItemStack, u: LootContext): ItemStack {
val blockEntity = u.getParamOrNull(LootContextParams.BLOCK_ENTITY) ?: return t
val result = t.tagNotNull["BlockEntityTag"] as? CompoundTag
val data = blockEntity.saveWithoutMetadata()
for (k in filter) {
data.remove(k)
}
if (result == null) {
t.tagNotNull["BlockEntityTag"] = data
} else {
for (k in data.allKeys) {
result[k] = data[k]!!
}
}
return t
}
override fun getType(): LootItemFunctionType {
return MItemFunctionTypes.COPY_TILE_NBT
}
override fun build(): LootItemFunction {
return this
}
companion object : Serializer<CopyTileNbtFunction> {
override fun serialize(
pJson: JsonObject,
pValue: CopyTileNbtFunction,
pSerializationContext: JsonSerializationContext
) {
pJson["filter"] = JsonArray().also { for (v in pValue.filter) it.add(v) }
}
override fun deserialize(
pJson: JsonObject,
pSerializationContext: JsonDeserializationContext
): CopyTileNbtFunction {
return CopyTileNbtFunction((pJson["filter"] as? JsonArray)?.stream()?.filter { it is JsonPrimitive }?.map { it.asString!! } ?: Stream.empty())
}
}
}

View File

@ -9,10 +9,11 @@ import ru.dbotthepony.mc.otm.menu.MatteryMenu
* [allowPull] and [allowPush] controls whenever player is allowed to change these options
*/
class ItemHandlerPlayerInput(val menu: MatteryMenu, val allowPull: Boolean = false, val allowPush: Boolean = false) {
inner class Piece(val side: RelativeSide) {
private val allowedFlags = MatteryDeviceBlockEntity.ItemHandlerMode.values().map { menu.mSynchronizer.bool() to it }
private val allowedFlags = MatteryDeviceBlockEntity.ItemHandlerMode.values().map { menu.mSynchronizer.bool() to it }
fun isAllowed(value: MatteryDeviceBlockEntity.ItemHandlerMode) = allowedFlags[value.ordinal].first.value
fun isAllowed(value: MatteryDeviceBlockEntity.ItemHandlerMode) = allowedFlags[value.ordinal].first.value
inner class Piece(val side: RelativeSide) {
fun isAllowed(value: MatteryDeviceBlockEntity.ItemHandlerMode) = this@ItemHandlerPlayerInput.isAllowed(value)
val pull = BooleanInputWithFeedback(menu)
val push = BooleanInputWithFeedback(menu)
@ -26,13 +27,9 @@ class ItemHandlerPlayerInput(val menu: MatteryMenu, val allowPull: Boolean = fal
}
fun configure(config: MatteryDeviceBlockEntity.ConfigurableItemHandler.Piece) {
for ((f, v) in allowedFlags) {
f.value = v in config.possibleViews
}
pull.with(config::automatePull)
push.with(config::automatePush)
input.withSupplier { config.mode }.withConsumer { if (it in config.possibleViews) config.mode = it }
input.withSupplier { config.mode }.withConsumer { if (isAllowed(it)) config.mode = it }
}
}
@ -50,6 +47,10 @@ class ItemHandlerPlayerInput(val menu: MatteryMenu, val allowPull: Boolean = fal
}
fun configure(config: MatteryDeviceBlockEntity.ConfigurableItemHandler) {
for ((f, v) in allowedFlags) {
f.value = v in config.possibleViews
}
for ((side, v) in config.pieces) {
pieces[side]!!.configure(v)
pieces[side]!!.default = config.defaults[side]!!

View File

@ -6,12 +6,14 @@ import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType
import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.registries.DeferredRegister
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.data.loot.CopyTileNbtFunction
import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction
object MItemFunctionTypes {
private val registry = DeferredRegister.create(Registries.LOOT_FUNCTION_TYPE, OverdriveThatMatters.MOD_ID)
val RANDOMIZER: LootItemFunctionType by registry.register("randomizer") { LootItemFunctionType(RandomizerFunction.Companion) }
val COPY_TILE_NBT: LootItemFunctionType by registry.register("copy_tile_nbt") { LootItemFunctionType(CopyTileNbtFunction.Companion) }
internal fun register(bus: IEventBus) {
registry.register(bus)