Make everything revolve around block sides rather than anything else

*spontaneous combustion*
This commit is contained in:
DBotThePony 2023-02-16 21:53:20 +07:00
parent 0ee5673ea9
commit 4fc05e1f3a
Signed by: DBot
GPG Key ID: DCC23B5715498507
35 changed files with 625 additions and 1022 deletions

View File

@ -26,6 +26,7 @@ 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.predicates.LootItemBlockStatePropertyCondition
import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue 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.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
@ -36,13 +37,13 @@ fun TileNbtCopy(source: String, strategy: CopyNbtFunction.MergeStrategy = CopyNb
} }
private val basicTags = arrayOf( private val basicTags = arrayOf(
TileNbtCopy(MatteryDeviceBlockEntity.REDSTONE_CONTROL_KEY), TileNbtCopy(MatteryBlockEntity.REDSTONE_CONTROL_KEY),
) )
private val poweredTags = arrayOf( private val poweredTags = arrayOf(
*basicTags, *basicTags,
TileNbtCopy(MatteryDeviceBlockEntity.ENERGY_KEY), TileNbtCopy(MatteryBlockEntity.ENERGY_KEY),
TileNbtCopy(MatteryDeviceBlockEntity.BATTERY_KEY), TileNbtCopy(MatteryBlockEntity.BATTERY_KEY),
) )
private val workerTags = arrayOf( private val workerTags = arrayOf(
@ -53,7 +54,7 @@ private val workerTags = arrayOf(
private val poweredMatterWorker = arrayOf( private val poweredMatterWorker = arrayOf(
*workerTags, *workerTags,
TileNbtCopy(MatteryDeviceBlockEntity.MATTER_STORAGE_KEY), TileNbtCopy(MatteryBlockEntity.MATTER_STORAGE_KEY),
) )
class LootTables(generator: DataGenerator) : LootTableProvider(generator.packOutput, setOf() /* because we don't fucking validate you fuck */, listOf() /* because we attach everything after class is constructed duh */) { class LootTables(generator: DataGenerator) : LootTableProvider(generator.packOutput, setOf() /* because we don't fucking validate you fuck */, listOf() /* because we attach everything after class is constructed duh */) {

View File

@ -8,9 +8,9 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition
import ru.dbotthepony.mc.otm.block.entity.tech.ChemicalGeneratorBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.ChemicalGeneratorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.EnergyCounterBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.EnergyCounterBlockEntity
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity.Companion.ENERGY_KEY import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.ENERGY_KEY
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity.Companion.MATTER_STORAGE_KEY import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.MATTER_STORAGE_KEY
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity.Companion.REDSTONE_CONTROL_KEY import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.REDSTONE_CONTROL_KEY
import ru.dbotthepony.mc.otm.block.entity.decorative.HoloSignBlockEntity import ru.dbotthepony.mc.otm.block.entity.decorative.HoloSignBlockEntity
import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.storage.AbstractStorageImportExport.Companion.FILTER_KEY import ru.dbotthepony.mc.otm.block.entity.storage.AbstractStorageImportExport.Companion.FILTER_KEY

View File

@ -1,15 +1,21 @@
package ru.dbotthepony.mc.otm.block.entity package ru.dbotthepony.mc.otm.block.entity
import com.google.common.collect.ImmutableSet
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap
import it.unimi.dsi.fastutil.objects.ReferenceArraySet
import net.minecraft.client.multiplayer.ClientLevel import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.core.SectionPos import net.minecraft.core.SectionPos
import net.minecraft.nbt.ByteTag
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.DoubleTag
import net.minecraft.nbt.FloatTag
import net.minecraft.nbt.StringTag
import net.minecraft.nbt.Tag import net.minecraft.nbt.Tag
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.level.ChunkPos import net.minecraft.world.level.ChunkPos
@ -28,20 +34,28 @@ import net.minecraftforge.event.entity.player.PlayerEvent
import net.minecraftforge.event.level.ChunkWatchEvent import net.minecraftforge.event.level.ChunkWatchEvent
import net.minecraftforge.event.level.LevelEvent import net.minecraftforge.event.level.LevelEvent
import net.minecraftforge.event.server.ServerStoppingEvent import net.minecraftforge.event.server.ServerStoppingEvent
import net.minecraftforge.items.IItemHandler
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
import ru.dbotthepony.mc.otm.compat.mekanism.Mattery2MekanismEnergyWrapper
import ru.dbotthepony.mc.otm.core.forValidRefs import ru.dbotthepony.mc.otm.core.forValidRefs
import ru.dbotthepony.mc.otm.core.forValidRefsBreak
import ru.dbotthepony.mc.otm.core.get import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.math.BlockRotation import ru.dbotthepony.mc.otm.core.math.BlockRotation
import ru.dbotthepony.mc.otm.core.math.RelativeSide import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.EnumValueCodec
import ru.dbotthepony.mc.otm.network.BlockEntitySyncPacket import ru.dbotthepony.mc.otm.network.BlockEntitySyncPacket
import ru.dbotthepony.mc.otm.network.FieldSynchronizer import ru.dbotthepony.mc.otm.network.FieldSynchronizer
import ru.dbotthepony.mc.otm.network.WorldNetworkChannel import ru.dbotthepony.mc.otm.network.WorldNetworkChannel
import ru.dbotthepony.mc.otm.oncePre import ru.dbotthepony.mc.otm.oncePre
import ru.dbotthepony.mc.otm.onceServer import ru.dbotthepony.mc.otm.onceServer
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.Collections
import java.util.EnumMap
import java.util.WeakHashMap import java.util.WeakHashMap
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KMutableProperty0
@ -63,29 +77,250 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
return blockState[(blockState.block as? RotatableMatteryBlock ?: return BlockRotation.NORTH).rotationProperty] return blockState[(blockState.block as? RotatableMatteryBlock ?: return BlockRotation.NORTH).rotationProperty]
} }
// Capabilities private val _sides = EnumMap<RelativeSide, Side>(RelativeSide::class.java)
val sides: Map<RelativeSide, Side> = Collections.unmodifiableMap(_sides)
private val caps = Reference2ObjectArrayMap<Capability<*>, CapInstance<*, *>>() private data class SidelessCap<T : Any>(val cap: T, var optional: LazyOptional<T>)
private val sidelessCaps = Reference2ObjectArrayMap<Capability<*>, SidelessCap<*>>()
fun <T : Any> getCapInstance(index: Capability<in T>): CapInstance<T, *>? { /**
return caps[index] as CapInstance<T, *>? * exposes capability when no side is specified
*/
protected fun <T : Any> exposeSideless(capability: Capability<T>, value: T) {
check(!sidelessCaps.containsKey(capability)) { "Already has globally exposed $capability!" }
sidelessCaps[capability] = SidelessCap(value, LazyOptional.of { value })
setChanged()
} }
protected fun <T : IMatteryEnergyStorage> energy(capability: T): StaticCap<T> { protected fun <T : Any> exposeAllSidesExcept(side: RelativeSide, capability: Capability<T>, value: T) {
return StaticCap(MatteryCapability.ENERGY, "energy", capability).alias(ForgeCapabilities.ENERGY) for ((k, v) in _sides) {
if (k != side) {
v.Cap(capability, value)
}
}
} }
abstract inner class CapInstance<T : Any, S : CapInstance<T, S>>(type: Capability<in T>, val name: String) : INBTSerializable<CompoundTag> { protected fun isSidelessExposed(capability: Capability<*>): Boolean {
private val types = ReferenceArraySet<Capability<in T>>() return sidelessCaps.containsKey(capability)
protected var valid = true }
abstract val capability: T
protected var optional by object : ReadWriteProperty<Any?, LazyOptional<T>> { protected fun removeSideless(capability: Capability<*>): Boolean {
if (sidelessCaps.remove(capability) != null) {
setChanged()
return true
}
return false
}
/**
* Exposes capability unconditionally, on all sides and sideless
*/
protected fun <T : Any> exposeGlobally(capability: Capability<T>, value: T) {
exposeSideless(capability, value)
for (side in _sides.values)
side.Cap(capability, value)
}
protected fun exposeEnergyGlobally(value: IMatteryEnergyStorage) {
exposeGlobally(ForgeCapabilities.ENERGY, value)
exposeGlobally(MatteryCapability.ENERGY, value)
if (isMekanismLoaded) {
exposeGlobally(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(value))
}
}
protected fun exposeEnergy(side: RelativeSide, value: IMatteryEnergyStorage) {
_sides[side]!!.Cap(ForgeCapabilities.ENERGY, value)
_sides[side]!!.Cap(MatteryCapability.ENERGY, value)
if (isMekanismLoaded) {
_sides[side]!!.Cap(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(value))
}
}
protected fun exposeEnergySideless( value: IMatteryEnergyStorage) {
exposeSideless(ForgeCapabilities.ENERGY, value)
exposeSideless(MatteryCapability.ENERGY, value)
if (isMekanismLoaded) {
exposeSideless(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(value))
}
}
protected fun exposeItemsGlobally(value: IItemHandler) {
exposeGlobally(ForgeCapabilities.ITEM_HANDLER, value)
}
enum class SideMode(val filter: FlowDirection, val automation: FlowDirection) {
DISABLED (FlowDirection.NONE, FlowDirection.NONE),
NONE (FlowDirection.BI_DIRECTIONAL, FlowDirection.NONE),
INPUT (FlowDirection.INPUT, FlowDirection.NONE),
OUTPUT (FlowDirection.OUTPUT, FlowDirection.NONE),
PULL (FlowDirection.INPUT, FlowDirection.INPUT),
PUSH (FlowDirection.OUTPUT, FlowDirection.OUTPUT),
PULL_ONLY (FlowDirection.BI_DIRECTIONAL, FlowDirection.INPUT),
PUSH_ONLY (FlowDirection.BI_DIRECTIONAL, FlowDirection.OUTPUT),
PULL_PUSH (FlowDirection.BI_DIRECTIONAL, FlowDirection.BI_DIRECTIONAL);
val isOpen = filter != FlowDirection.NONE
companion object {
@JvmField
val BI_SET: ImmutableSet<SideMode> = ImmutableSet.of(NONE, INPUT, OUTPUT, PULL, PUSH, PULL_ONLY, PUSH_ONLY, PULL_PUSH, DISABLED)
@JvmField
val INPUT_SET: ImmutableSet<SideMode> = ImmutableSet.of(INPUT, PULL, DISABLED)
@JvmField
val OUTPUT_SET: ImmutableSet<SideMode> = ImmutableSet.of(OUTPUT, PUSH, DISABLED)
@JvmField
val CODEC = EnumValueCodec(SideMode::class.java)
}
}
fun interface SideModeListener {
fun sideModeChanges(config: Side.ModeState, new: SideMode, old: SideMode)
}
inner class Side(val side: RelativeSide) : INBTSerializable<CompoundTag> {
init {
check(!_sides.containsKey(side)) { "dafuq are you trying to do" }
_sides[side] = this
}
private val caps = Reference2ObjectArrayMap<Capability<*>, Cap<*>>()
private val modeStates = Object2ObjectArrayMap<String, ModeState>()
private val data = Object2ObjectArrayMap<ResourceLocation, INBTSerializable<Tag>>()
val isEmpty get() = caps.isEmpty() && modeStates.isEmpty()
operator fun <T : Any> get(capability: Capability<T>): Cap<T>? {
return caps[capability] as Cap<T>?
}
operator fun get(index: String): ModeState? {
return modeStates[index]
}
fun addData(index: ResourceLocation, data: INBTSerializable<*>) {
this.data[index] = data as INBTSerializable<Tag>
}
fun getData(index: ResourceLocation): INBTSerializable<*>? {
return data[index]
}
fun invalidate() {
for (cap in caps.values)
cap.invalidate()
}
fun revive() {
for (cap in caps.values)
cap.revive()
}
override fun serializeNBT(): CompoundTag {
return CompoundTag().also {
val modelist = CompoundTag()
for (cap in modeStates.values) {
modelist[cap.name] = cap.serializeNBT()
}
it["Modes"] = modelist
}
}
override fun deserializeNBT(nbt: CompoundTag) {
if (nbt.contains("Modes")) {
val caplist = nbt.getCompound("Modes")
for (state in modeStates.values) {
if (state.name in caplist) {
state.deserializeNBT(caplist.getString(state.name))
}
}
}
}
inner class ModeState(val name: String, val possibleValues: ImmutableSet<SideMode> = SideMode.BI_SET) : INBTSerializable<StringTag> {
init {
check(!modeStates.containsKey(name)) { "Already has config with name $name on side $side" }
modeStates[name] = this
}
val side get() = this@Side.side
var mode by synchronizer.Field(possibleValues.first(), SideMode.CODEC, setter = { value, access, setByRemote ->
require(value in possibleValues) { "Value $value is not allowed (allowed values: $possibleValues)" }
val old = access.read()
if (value != old) {
access.write(value)
listeners.forValidRefs {
it.sideModeChanges(this, value, old)
}
}
}, name = "SideConfig/$side/$name")
fun isAllowed(value: SideMode): Boolean = value in possibleValues
private val listeners = ArrayList<WeakReference<SideModeListener>>()
fun addListener(listener: SideModeListener) {
var hit = false
listeners.forValidRefsBreak {
if (it === listener) {
hit = true
return@forValidRefsBreak true
}
return@forValidRefsBreak false
}
if (!hit) {
listeners.add(WeakReference(listener))
}
}
override fun serializeNBT(): StringTag {
return StringTag.valueOf(mode.name)
}
override fun deserializeNBT(nbt: StringTag) {
mode = SideMode.valueOf(nbt.asString)
}
fun deserializeNBT(nbt: String) {
mode = SideMode.valueOf(nbt)
}
}
inner class Cap<T : Any>(val type: Capability<in T>, val capability: T) {
init {
check(!caps.containsKey(type)) { "Already has capability $type on side $side" }
caps[type] = this
}
private var isExposed = true
private var isValid = true
private var isRemoved = false
var optional: LazyOptional<T> by object : ReadWriteProperty<Any?, LazyOptional<T>> {
private var value: LazyOptional<T>? = null private var value: LazyOptional<T>? = null
override fun getValue(thisRef: Any?, property: KProperty<*>): LazyOptional<T> { override fun getValue(thisRef: Any?, property: KProperty<*>): LazyOptional<T> {
if (value == null) if (value == null) {
value = if (valid) LazyOptional.of { capability } else LazyOptional.empty() value = LazyOptional.of { capability }
}
return value!! return value!!
} }
@ -94,205 +329,89 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
this.value = value this.value = value
} }
} }
private set
init { fun remove() {
check(!caps.values.any { it.name == name }) { "Already has capability with name $name!" } if (!isRemoved) {
check(!caps.containsKey(type)) { "Already has capability with type $type!" } isRemoved = true
caps[type] = this val removed = caps.remove(type)
types.add(type) check(removed == this) { "$removed != $this" }
} optional.invalidate()
fun alias(type: Capability<in T>): S {
if (type !in types) {
check(!caps.containsKey(type)) { "Already has capability with type $type!" }
caps[type] = this
types.add(type)
}
return this as S
}
override fun toString(): String {
return "${this@MatteryBlockEntity} at $blockPos CapInstance[name = $name, capability = $capability]"
}
override fun serializeNBT(): CompoundTag {
return CompoundTag().also {
var sides = 0
for (i in 0 .. 5)
if (exposedSides[i].first)
sides = sides.or(1 shl (i + 1))
it["sides"] = sides.toShort()
if (capability is INBTSerializable<*>)
it["capability"] = (capability as INBTSerializable<Tag>).serializeNBT()
} }
} }
override fun deserializeNBT(nbt: CompoundTag) { fun close() {
var sides = 0 if (!isRemoved && isExposed) {
isExposed = false
if (nbt.contains("sides")) { optional.invalidate()
sides = nbt.getInt("sides")
}
for (i in 0 .. 5) {
val isExposed = sides and (1 shl (1 + i)) == 1
if (isExposed && valid) {
exposedSides[i] = true to LazyOptional.of { capability }
} else {
exposedSides[i] = isExposed to LazyOptional.empty()
}
}
val tag = nbt["capability"]
if (tag != null && capability is INBTSerializable<*>) {
// will throw classcastexception if serialized type is wrong
(capability as INBTSerializable<Tag>).deserializeNBT(tag)
}
}
protected val exposedSides = Array<Pair<Boolean, LazyOptional<T>>>(6) { true to LazyOptional.of { capability } }
fun exposeAt(side: RelativeSide): S {
if (!exposedSides[side.ordinal].first) {
if (valid) {
setChanged() setChanged()
exposedSides[side.ordinal] = true to LazyOptional.of { capability }
} else {
exposedSides[side.ordinal] = true to LazyOptional.empty()
} }
} }
return this as S fun expose() {
if (!isRemoved && !isExposed) {
isExposed = true
if (isValid) {
optional = LazyOptional.of { capability }
setChanged()
} }
fun closeAt(side: RelativeSide): S {
if (exposedSides[side.ordinal].first) {
exposedSides[side.ordinal].second.invalidate()
exposedSides[side.ordinal] = false to LazyOptional.empty()
}
return this as S
}
fun closeAll(): S {
for (side in RelativeSide.values())
closeAt(side)
return this as S
}
fun exposeAll(): S {
for (side in RelativeSide.values())
exposeAt(side)
return this as S
}
fun exposeFront() = exposeAt(RelativeSide.FRONT)
fun exposeBack() = exposeAt(RelativeSide.BACK)
fun exposeLeft() = exposeAt(RelativeSide.LEFT)
fun exposeRight() = exposeAt(RelativeSide.RIGHT)
fun exposeTop() = exposeAt(RelativeSide.TOP)
fun exposeBottom() = exposeAt(RelativeSide.BOTTOM)
fun closeFront() = closeAt(RelativeSide.FRONT)
fun closeBack() = closeAt(RelativeSide.BACK)
fun closeLeft() = closeAt(RelativeSide.LEFT)
fun closeRight() = closeAt(RelativeSide.RIGHT)
fun closeTop() = closeAt(RelativeSide.TOP)
fun closeBottom() = closeAt(RelativeSide.BOTTOM)
fun isExposedAt(side: RelativeSide): Boolean {
return exposedSides[side.ordinal].first
}
fun isExposedAt(side: Direction): Boolean {
return isExposedAt(blockRotation.dir2Side(side))
}
fun get(side: Direction? = null): LazyOptional<T> {
if (!valid) {
return LazyOptional.empty()
}
if (side == null) {
return optional
} else {
return exposedSides[blockRotation.dir2Side(side).ordinal].second
} }
} }
fun invalidate() { fun invalidate() {
if (valid) { if (!isRemoved && isValid) {
for ((_, v) in exposedSides) isValid = false
v.invalidate()
optional.invalidate() optional.invalidate()
valid = false setChanged()
} }
} }
fun revive() { fun revive() {
if (!valid) { if (!isRemoved && !isValid) {
for ((i, pair) in exposedSides.withIndex()) isValid = true
if (pair.first)
exposedSides[i] = true to LazyOptional.of { capability }
if (isExposed) {
optional = LazyOptional.of { capability } optional = LazyOptional.of { capability }
valid = true setChanged()
} }
} }
} }
inner class StaticCap<T : Any>(type: Capability<in T>, name: String, override val capability: T) : CapInstance<T, StaticCap<T>>(type, name)
inner class DynamicCap<T : Any>(type: Capability<in T>, name: String, capability: T) : CapInstance<T, DynamicCap<T>>(type, name) {
override var capability: T = capability
private set(value) {
field = value
if (valid) {
val old = ArrayList<LazyOptional<T>>(7)
old.add(optional)
val new = LazyOptional.of { value }
optional = new
for ((i, pair) in exposedSides.withIndex()) {
if (pair.first) {
old.add(pair.second)
exposedSides[i] = true to LazyOptional.of { value }
} }
} }
old.forEach(LazyOptional<T>::invalidate) val front = Side(RelativeSide.FRONT)
} val back = Side(RelativeSide.BACK)
} val left = Side(RelativeSide.LEFT)
val right = Side(RelativeSide.RIGHT)
val top = Side(RelativeSide.TOP)
val bottom = Side(RelativeSide.BOTTOM)
override fun <T : Any> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (side != null) {
val get = _sides[blockRotation.dir2Side(side)]!![cap]
if (get != null)
return get.optional
return super.getCapability(cap, side)
} }
// /Capabilities return sidelessCaps[cap]?.optional?.cast() ?: super.getCapability(cap, side)
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
return caps[cap]?.get(side)?.cast() ?: super.getCapability(cap, side)
} }
override fun invalidateCaps() { override fun invalidateCaps() {
super.invalidateCaps() super.invalidateCaps()
for (cap in caps.values) for (side in sides.values)
cap.invalidate() side.invalidate()
} }
override fun reviveCaps() { override fun reviveCaps() {
super.reviveCaps() super.reviveCaps()
for (cap in caps.values) for (side in sides.values)
cap.revive() side.revive()
} }
private data class Savetable0<T : Tag, V : Any>(val type: Class<T>, val property: KProperty0<V>, val name: String, val serialize: (V) -> T, val deserialize: (V, T) -> Unit) private data class Savetable0<T : Tag, V : Any>(val type: Class<T>, val property: KProperty0<V>, val name: String, val serialize: (V) -> T, val deserialize: (V, T) -> Unit)
@ -304,7 +423,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
/** /**
* Save and load object state * Save and load object state
*/ */
protected fun <T : Tag, V : Any> savetable(type: Class<T>, property: KProperty0<V>, name: String = property.name, serialize: (V) -> T, deserialize: (V, T?) -> Unit) { protected fun <T : Tag, V : Any> savetable(type: Class<T>, property: KProperty0<V>, name: String = property.name, serialize: (V) -> T, deserialize: (V, T) -> Unit) {
check(!savetables0.any { it.name == name }) { "Already has save field with name $name" } check(!savetables0.any { it.name == name }) { "Already has save field with name $name" }
check(!savetables1.any { it.name == name }) { "Already has save field with name $name" } check(!savetables1.any { it.name == name }) { "Already has save field with name $name" }
savetables0.add(Savetable0(type, property, name, serialize, deserialize)) savetables0.add(Savetable0(type, property, name, serialize, deserialize))
@ -313,7 +432,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
/** /**
* Save and load value * Save and load value
*/ */
protected fun <T : Tag, V : Any> savetable(type: Class<T>, property: KMutableProperty0<V>, name: String = property.name, serialize: (V) -> T, deserialize: (T?) -> V) { protected fun <T : Tag, V : Any> savetable(type: Class<T>, property: KMutableProperty0<V>, name: String = property.name, serialize: (V) -> T, deserialize: (T) -> V) {
check(!savetables0.any { it.name == name }) { "Already has save field with name $name" } check(!savetables0.any { it.name == name }) { "Already has save field with name $name" }
check(!savetables1.any { it.name == name }) { "Already has save field with name $name" } check(!savetables1.any { it.name == name }) { "Already has save field with name $name" }
savetables1.add(Savetable1(type, property, name, serialize, deserialize)) savetables1.add(Savetable1(type, property, name, serialize, deserialize))
@ -336,24 +455,38 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
/** /**
* Save and load object state * Save and load object state
*/ */
protected inline fun <reified T : Tag, V : Any> savetable(property: KProperty0<V>, name: String = property.name, noinline serialize: (V) -> T, noinline deserialize: (V, T?) -> Unit) { protected inline fun <reified T : Tag, V : Any> savetable(property: KProperty0<V>, name: String = property.name, noinline serialize: (V) -> T, noinline deserialize: (V, T) -> Unit) {
savetable(T::class.java, property, name, serialize, deserialize) savetable(T::class.java, property, name, serialize, deserialize)
} }
/** /**
* Save and load value * Save and load value
*/ */
protected inline fun <reified T : Tag, V : Any> savetable(property: KMutableProperty0<V>, name: String = property.name, noinline serialize: (V) -> T, noinline deserialize: (T?) -> V) { protected inline fun <reified T : Tag, V : Any> savetable(property: KMutableProperty0<V>, name: String = property.name, noinline serialize: (V) -> T, noinline deserialize: (T) -> V) {
savetable(T::class.java, property, name, serialize, deserialize) savetable(T::class.java, property, name, serialize, deserialize)
} }
protected fun savetableFloat(property: KMutableProperty0<Float>, name: String = property.name) {
savetable(FloatTag::class.java, property, name, { FloatTag.valueOf(it) }, { tag -> tag.asFloat })
}
protected fun savetableDouble(property: KMutableProperty0<Double>, name: String = property.name) {
savetable(DoubleTag::class.java, property, name, { DoubleTag.valueOf(it) }, { tag -> tag.asDouble })
}
protected fun savetableBoolean(property: KMutableProperty0<Boolean>, name: String = property.name) {
savetable(ByteTag::class.java, property, name, { if (it) ByteTag.ONE else ByteTag.ZERO }, { tag -> tag.asInt > 0 })
}
override fun saveAdditional(nbt: CompoundTag) { override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt) super.saveAdditional(nbt)
if (caps.isNotEmpty()) { if (_sides.values.any { !it.isEmpty }) {
nbt["Capabilities"] = CompoundTag().also { nbt["Sides"] = CompoundTag().also {
for (cap in caps.values) { for (side in _sides.values) {
it[cap.name] = cap.serializeNBT() if (!side.isEmpty) {
it[side.side.name] = side.serializeNBT()
}
} }
} }
} }
@ -370,13 +503,12 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
override fun load(nbt: CompoundTag) { override fun load(nbt: CompoundTag) {
super.load(nbt) super.load(nbt)
if (nbt.contains("Capabilities")) { if (nbt.contains("Sides")) {
@Suppress("name_shadowing") val tag = nbt.getCompound("Sides")
val nbt = nbt.getCompound("Capabilities")
for (cap in caps.values) { for (side in _sides.values) {
if (nbt.contains(cap.name)) { if (side.side.name in tag) {
cap.deserializeNBT(nbt.getCompound(cap.name)) side.deserializeNBT(tag.getCompound(side.side.name))
} }
} }
} }
@ -387,7 +519,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
if (value != null && data.type.isAssignableFrom(value.javaClass)) { if (value != null && data.type.isAssignableFrom(value.javaClass)) {
(data.deserialize as (Any, Tag) -> Unit).invoke(data.property.get(), value) (data.deserialize as (Any, Tag) -> Unit).invoke(data.property.get(), value)
} else if (value != null) { } else if (value != null) {
throw ClassCastException("Expected ") throw ClassCastException("Expected ${data.type.canonicalName}, got ${value.javaClass.canonicalName}")
} }
} }
@ -396,6 +528,8 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
if (value != null && data.type.isAssignableFrom(value.javaClass)) { if (value != null && data.type.isAssignableFrom(value.javaClass)) {
(data.property as KMutableProperty0<Any>).set((data.deserialize as (Tag) -> Any).invoke(value)) (data.property as KMutableProperty0<Any>).set((data.deserialize as (Tag) -> Any).invoke(value))
} else if (value != null) {
throw ClassCastException("Expected ${data.type.canonicalName}, got ${value.javaClass.canonicalName}")
} }
} }
} }

View File

@ -9,6 +9,7 @@ import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.level.BlockGetter import net.minecraft.world.level.BlockGetter
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
@ -26,22 +27,25 @@ import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(p_155228_, p_155229_, p_155230_) { abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(p_155228_, p_155229_, p_155230_) {
abstract val energy: BlockEnergyStorageImpl? val batteryContainer = MatteryContainer(::setChangedLight, 1)
private var valid = true
val batteryContainer = MatteryContainer(this::setChangedLight, 1) init {
savetable(::batteryContainer, BATTERY_KEY)
}
protected fun batteryChargeLoop() { protected fun batteryChargeLoop() {
val energy = matteryEnergy
if (energy == null || !batteryContainer.any { !it.isEmpty }) if (energy == null || !batteryContainer.any { !it.isEmpty })
return return
var demand = energy!!.receiveEnergy(energy!!.missingPower, true) var demand = energy.receiveEnergy(energy.missingPower, true)
if (demand.isZero) return if (demand.isZero) return
for (stack in batteryContainer) { for (stack in batteryContainer) {
if (!stack.isEmpty) { if (!stack.isEmpty) {
stack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { stack.getCapability(ForgeCapabilities.ENERGY).ifPresentK {
val diff = it.extractEnergy(demand, false) val diff = it.extractEnergy(demand, false)
energy!!.receiveEnergy(diff, false) energy.receiveEnergy(diff, false)
demand -= diff demand -= diff
} }
@ -51,42 +55,6 @@ abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229
} }
} }
override fun invalidateCaps() {
super.invalidateCaps()
energy?.invalidate()
valid = false
}
override fun reviveCaps() {
super.reviveCaps()
energy?.revive()
valid = true
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid && (cap === MatteryCapability.ENERGY || cap === ForgeCapabilities.ENERGY) && energy != null)
return energy!!.resolver.cast()
return super.getCapability(cap, side)
}
public override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
if (energy != null)
nbt[ENERGY_KEY] = energy!!.serializeNBT()
nbt[BATTERY_KEY] = batteryContainer.serializeNBT()
}
override fun load(nbt: CompoundTag) {
if (energy != null)
nbt.ifHas(ENERGY_KEY, CompoundTag::class.java, energy!!::deserializeNBT)
batteryContainer.deserializeNBT(nbt[BATTERY_KEY])
super.load(nbt)
}
companion object { companion object {
fun appendHoverText(itemStack: ItemStack, blockGetter: BlockGetter?, tooltips: MutableList<Component>, flag: TooltipFlag) { fun appendHoverText(itemStack: ItemStack, blockGetter: BlockGetter?, tooltips: MutableList<Component>, flag: TooltipFlag) {
val tag = itemStack.tag?.get(BlockItem.BLOCK_ENTITY_TAG) as? CompoundTag ?: return val tag = itemStack.tag?.get(BlockItem.BLOCK_ENTITY_TAG) as? CompoundTag ?: return

View File

@ -11,6 +11,7 @@ import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.level.BlockGetter import net.minecraft.world.level.BlockGetter
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.getDecimal import ru.dbotthepony.mc.otm.core.math.getDecimal
@ -254,10 +255,7 @@ abstract class MatteryWorkerBlockEntity<JobType : MatteryWorkerBlockEntity.Job>(
errorTicksAnim = 0 errorTicksAnim = 0
idleTicksAnim++ idleTicksAnim++
if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue( if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.IDLE) {
WorkerState.WORKER_STATE
) != WorkerState.IDLE
) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS) level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
} }
@ -265,6 +263,7 @@ abstract class MatteryWorkerBlockEntity<JobType : MatteryWorkerBlockEntity.Job>(
} }
var availableTicks = 1.0 var availableTicks = 1.0
val energy = matteryEnergy
while (!isIdling && weakGreaterThan(availableTicks, 0.0) && throttleTicks <= 0) { while (!isIdling && weakGreaterThan(availableTicks, 0.0) && throttleTicks <= 0) {
if (redstoneControl.isBlockedByRedstone) { if (redstoneControl.isBlockedByRedstone) {
@ -288,7 +287,7 @@ abstract class MatteryWorkerBlockEntity<JobType : MatteryWorkerBlockEntity.Job>(
currentJob = job currentJob = job
} }
if (!currentJob.powerUsage.isZero && (energy == null || energy!!.batteryLevel.isZero)) { if (!currentJob.powerUsage.isZero && (energy == null || energy.batteryLevel.isZero)) {
idleReason = IdleReason.POWER idleReason = IdleReason.POWER
isIdling = true isIdling = true
idleTicksAnim++ idleTicksAnim++

View File

@ -95,35 +95,19 @@ class CargoCrateBlockEntity(
} }
} }
override fun invalidateCaps() { init {
super.invalidateCaps() exposeItemsGlobally(handler)
handler.invalidate() savetable(::container, INVENTORY_KEY)
}
override fun reviveCaps() {
super.reviveCaps()
handler.revive()
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (cap == ForgeCapabilities.ITEM_HANDLER)
return handler.get().cast()
return super.getCapability(cap, side)
} }
override fun saveAdditional(nbt: CompoundTag) { override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt) super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
lootTable?.let { nbt[LOOT_TABLE_KEY] = it.toString() } lootTable?.let { nbt[LOOT_TABLE_KEY] = it.toString() }
lootTableSeed?.let { nbt[LOOT_TABLE_SEED_KEY] = it } lootTableSeed?.let { nbt[LOOT_TABLE_SEED_KEY] = it }
} }
override fun load(nbt: CompoundTag) { override fun load(nbt: CompoundTag) {
super.load(nbt) super.load(nbt)
container.deserializeNBT(nbt[INVENTORY_KEY])
lootTable = nbt.map(LOOT_TABLE_KEY) { it: StringTag -> ResourceLocation.tryParse(it.asString) } lootTable = nbt.map(LOOT_TABLE_KEY) { it: StringTag -> ResourceLocation.tryParse(it.asString) }
lootTableSeed = (nbt[LOOT_TABLE_SEED_KEY] as LongTag?)?.asLong lootTableSeed = (nbt[LOOT_TABLE_SEED_KEY] as LongTag?)?.asLong
} }

View File

@ -49,8 +49,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, p_155229_, p_155230_), IMatterGraphNode, IDroppableContainer { MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, p_155229_, p_155230_), IMatterGraphNode, IDroppableContainer {
override val matterNode = Graph6Node<IMatterGraphNode>(this) override val matterNode = Graph6Node<IMatterGraphNode>(this)
private val resolverNode = LazyOptional.of { this } val energy = WorkerEnergyStorage(this, ENERGY_VALUES)
override val energy = WorkerEnergyStorage(this, ENERGY_VALUES)
var isBottling: Boolean = true var isBottling: Boolean = true
set(value) { set(value) {
@ -98,8 +97,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
} }
override val droppableContainer: Container override val droppableContainer by ::container
get() = container
val itemHandler = container.handler(object : MatteryContainerHooks { val itemHandler = container.handler(object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean { override fun canInsert(slot: Int, stack: ItemStack): Boolean {
@ -125,6 +123,19 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
} }
init {
exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeItemsGlobally(itemHandler)
savetableBoolean(::isBottling)
savetable(::energy, ENERGY_KEY)
savetable(::matter, MATTER_STORAGE_KEY)
savetable(::container, INVENTORY_KEY)
exposeEnergyGlobally(energy)
}
private var initialCapacity: Decimal? = null private var initialCapacity: Decimal? = null
private var lastWorkStack: ItemStack? = null private var lastWorkStack: ItemStack? = null
@ -139,61 +150,10 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatterNetworkGraph.discoverFull(this, matterNode) MatterNetworkGraph.discoverFull(this, matterNode)
} }
private var valid = true
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
itemHandler.invalidate()
matter.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
itemHandler.revive()
matter.revive()
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) {
if (cap == MatteryCapability.MATTER) {
return matter.get().cast()
}
if (cap == ForgeCapabilities.ITEM_HANDLER) {
return itemHandler.get().cast()
}
if (cap == MatteryCapability.MATTER_NODE) {
return resolverNode.cast()
}
}
return super.getCapability(cap, side)
}
override val defaultDisplayName: Component
get() = MBlocks.MATTER_BOTTLER.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterBottlerMenu(containerID, inventory, this) return MatterBottlerMenu(containerID, inventory, this)
} }
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
nbt[IS_BOTTLING_KEY] = isBottling
nbt[MATTER_STORAGE_KEY] = matter.serializeNBT()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
isBottling = nbt.getBoolean(IS_BOTTLING_KEY)
nbt.map(MATTER_STORAGE_KEY, matter::deserializeNBT)
nbt.map(INVENTORY_KEY, container::deserializeNBT)
}
fun getWorkProgress(): Float { fun getWorkProgress(): Float {
val lastWorkStack = lastWorkStack ?: return 0f val lastWorkStack = lastWorkStack ?: return 0f
val initialCapacity = initialCapacity ?: return 0f val initialCapacity = initialCapacity ?: return 0f

View File

@ -38,7 +38,6 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
private set private set
override val matterNode = Graph6Node<IMatterGraphNode>(this) override val matterNode = Graph6Node<IMatterGraphNode>(this)
private val resolverNode = LazyOptional.of { this }
override val canSetMatterLevel: Boolean override val canSetMatterLevel: Boolean
get() = false get() = false
@ -133,8 +132,6 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
override val matterFlow: FlowDirection override val matterFlow: FlowDirection
get() = FlowDirection.BI_DIRECTIONAL get() = FlowDirection.BI_DIRECTIONAL
private var resolver = LazyOptional.of { this }
val container = object : MatteryContainer(this::setChangedLight, BatteryBankBlockEntity.CAPACITY) { val container = object : MatteryContainer(this::setChangedLight, BatteryBankBlockEntity.CAPACITY) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) { override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old) super.setChanged(slot, new, old)
@ -147,48 +144,18 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
synchronizer.bool(false, name = "capacitor$it") synchronizer.bool(false, name = "capacitor$it")
} }
override val droppableContainer: Container override val droppableContainer by ::container
get() = container
override val defaultDisplayName: Component
get() = MACHINE_NAME
override fun saveAdditional(nbt: CompoundTag) { init {
super.saveAdditional(nbt) savetable(::container, INVENTORY_KEY)
nbt[INVENTORY_KEY] = container.serializeNBT() exposeGlobally(MatteryCapability.MATTER, this)
} exposeGlobally(MatteryCapability.MATTER_NODE, this)
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(INVENTORY_KEY, container::deserializeNBT)
} }
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterCapacitorBankMenu(containerID, inventory, this) return MatterCapacitorBankMenu(containerID, inventory, this)
} }
private var valid = true
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
resolver.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
resolver = LazyOptional.of { this }
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) {
if (cap === MatteryCapability.MATTER) return resolver.cast()
if (cap === MatteryCapability.MATTER_NODE) return resolverNode.cast()
}
return super.getCapability(cap, side)
}
override fun setRemoved() { override fun setRemoved() {
super.setRemoved() super.setRemoved()
matterNode.destroy(::MatterNetworkGraph) matterNode.destroy(::MatterNetworkGraph)
@ -204,8 +171,4 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
override fun getMatterHandler(): IMatterStorage { override fun getMatterHandler(): IMatterStorage {
return this return this
} }
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_capacitor_bank")
}
} }

View File

@ -130,23 +130,28 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
} }
} }
override val energy = WorkerEnergyStorage(this, ENERGY_VALUES) val energy = WorkerEnergyStorage(this, ENERGY_VALUES)
private var valid = true
init {
exposeEnergyGlobally(energy)
savetable(::energy, ENERGY_KEY)
}
override val matterNode = Graph6Node<IMatterGraphNode>(this) override val matterNode = Graph6Node<IMatterGraphNode>(this)
val matter = MatterStorageImpl(this::setChangedLight, FlowDirection.OUTPUT, ::CAPACITY) val matter = MatterStorageImpl(::setChangedLight, FlowDirection.OUTPUT, ::CAPACITY)
private var resolverMatter = LazyOptional.of { matter } init {
private var resolverNode = LazyOptional.of { this } exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
savetable(::matter, MATTER_STORAGE_KEY)
}
// вход, выход // вход, выход
val container = MatteryContainer(this::setChangedLight, 3) val container = MatteryContainer(this::setChangedLight, 3)
override val droppableContainer by ::container
override val droppableContainer: Container val itemHandler = container.handler(object : MatteryContainerHooks {
get() = container
private val itemHandler = LazyOptional.of<IItemHandler> {
container.handler(object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean { override fun canInsert(slot: Int, stack: ItemStack): Boolean {
return slot == INPUT_SLOT && MatterManager.canDecompose(stack) return slot == INPUT_SLOT && MatterManager.canDecompose(stack)
} }
@ -155,49 +160,16 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
return slot != INPUT_SLOT return slot != INPUT_SLOT
} }
}) })
}
override val defaultDisplayName: Component init {
get() = MBlocks.MATTER_DECOMPOSER.name exposeItemsGlobally(itemHandler)
savetable(::container, INVENTORY_KEY)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterDecomposerMenu(containerID, inventory, this) return MatterDecomposerMenu(containerID, inventory, this)
} }
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
nbt[MATTER_STORAGE_KEY] = matter.serializeNBT()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(INVENTORY_KEY, container::deserializeNBT)
nbt.map(MATTER_STORAGE_KEY, matter::deserializeNBT)
}
override fun reviveCaps() {
valid = true
super.reviveCaps()
resolverMatter = LazyOptional.of { matter }
}
override fun invalidateCaps() {
valid = false
super.invalidateCaps()
resolverMatter.invalidate()
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) {
if (cap == MatteryCapability.MATTER) return resolverMatter.cast()
if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast()
if (cap == ForgeCapabilities.ITEM_HANDLER) return itemHandler.cast()
}
return super.getCapability(cap, side)
}
override fun onJobFinish(job: DecomposerJob): Status { override fun onJobFinish(job: DecomposerJob): Status {
if (job.toDust) { if (job.toDust) {
job.matterValue = moveMatterAsDustIntoContainer(job.matterValue, container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING) job.matterValue = moveMatterAsDustIntoContainer(job.matterValue, container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING)

View File

@ -49,27 +49,9 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return MatterPanelMenu(containerID, inventory, this) return MatterPanelMenu(containerID, inventory, this)
} }
private var valid = true init {
exposeGlobally(MatteryCapability.MATTER_NODE, this)
override fun invalidateCaps() { exposeGlobally(MatteryCapability.TASK, this)
super.invalidateCaps()
valid = false
resolver.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
resolver = LazyOptional.of { this }
}
private var resolver = LazyOptional.of { this }
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid && (cap === MatteryCapability.MATTER_NODE || cap === MatteryCapability.TASK))
return resolver.cast()
return super.getCapability(cap, side)
} }
override fun setLevel(p_155231_: Level) { override fun setLevel(p_155231_: Level) {

View File

@ -82,12 +82,9 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
val container = MatteryContainer(this::itemContainerUpdated, 1) val container = MatteryContainer(this::itemContainerUpdated, 1)
override val droppableContainer: Container override val droppableContainer by ::container
get() = container
override val matterNode = Graph6Node<IMatterGraphNode>(this) override val matterNode = Graph6Node<IMatterGraphNode>(this)
private var resolverNode = LazyOptional.of { this } val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_CONFIG)
private var valid = true
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_CONFIG)
override fun getMatterHandler(): IMatterStorage { override fun getMatterHandler(): IMatterStorage {
return matter return matter
@ -103,18 +100,14 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
} }
}) })
override fun invalidateCaps() { init {
super.invalidateCaps() exposeItemsGlobally(itemHandler)
matter.invalidate() exposeEnergyGlobally(energy)
itemHandler.invalidate() exposeGlobally(MatteryCapability.MATTER, matter)
resolverNode.invalidate() exposeGlobally(MatteryCapability.MATTER_NODE, this)
} savetable(::energy, ENERGY_KEY)
savetable(::container, INVENTORY_KEY)
override fun reviveCaps() { savetable(::matter, MATTER_STORAGE_KEY)
super.reviveCaps()
matter.revive()
itemHandler.revive()
resolverNode = LazyOptional.of { this }
} }
override fun setRemoved() { override fun setRemoved() {
@ -129,33 +122,6 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
MatterNetworkGraph.discoverFull(this, matterNode) MatterNetworkGraph.discoverFull(this, matterNode)
} }
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[MATTER_STORAGE_KEY] = matter.serializeNBT()
nbt[INVENTORY_KEY] = container.serializeNBT()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(MATTER_STORAGE_KEY, matter::deserializeNBT)
nbt.map(INVENTORY_KEY, container::deserializeNBT)
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (!valid)
return super.getCapability(cap, side)
return when (cap) {
ForgeCapabilities.ITEM_HANDLER -> itemHandler.get().cast()
MatteryCapability.MATTER -> matter.get().cast()
MatteryCapability.MATTER_NODE -> resolverNode.cast()
else -> super.getCapability(cap, side)
}
}
override val defaultDisplayName: Component
get() = MBlocks.MATTER_RECYCLER.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterRecyclerMenu(containerID, inventory, this) return MatterRecyclerMenu(containerID, inventory, this)
} }

View File

@ -105,24 +105,23 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
} }
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_VALUES) val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_VALUES)
override val matterNode = Graph6Node<IMatterGraphNode>(this) override val matterNode = Graph6Node<IMatterGraphNode>(this)
private val resolverNode = LazyOptional.of { this } val matter = MatterStorageImpl(this::matterLevelUpdated, FlowDirection.INPUT, ::MATTER_CAPACITY)
val matter = MatterStorageImpl(
this::matterLevelUpdated,
FlowDirection.INPUT,
::MATTER_CAPACITY
)
val container = MatteryContainer(this::itemContainerUpdated, 5) val container = MatteryContainer(this::itemContainerUpdated, 5)
private val itemHandler = container.handler(MatteryContainerHandler.OnlyOut) val itemHandler = container.handler(MatteryContainerHandler.OnlyOut)
override val droppableContainer by ::container
override val defaultDisplayName: Component init {
get() = MBlocks.MATTER_REPLICATOR.name exposeEnergyGlobally(energy)
exposeItemsGlobally(itemHandler)
exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
override val droppableContainer: Container savetable(::energy, ENERGY_KEY)
get() = container savetable(::matter, MATTER_STORAGE_KEY)
savetable(::container, INVENTORY_KEY)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterReplicatorMenu(containerID, inventory, this) return MatterReplicatorMenu(containerID, inventory, this)
@ -270,41 +269,6 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return Status.SUCCESS return Status.SUCCESS
} }
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
nbt[MATTER_STORAGE_KEY] = matter.serializeNBT()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(INVENTORY_KEY, container::deserializeNBT)
nbt.map(MATTER_STORAGE_KEY, matter::deserializeNBT)
}
private var valid = true
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
itemHandler.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
itemHandler.revive()
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) {
if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast()
if (cap == ForgeCapabilities.ITEM_HANDLER) return itemHandler.get().cast()
}
return super.getCapability(cap, side)
}
companion object { companion object {
private val BASE_CONSUMPTION get() = _BASE_CONSUMPTION.get() private val BASE_CONSUMPTION get() = _BASE_CONSUMPTION.get()
private val DRAIN_MULT get() = _DRAIN_MULT.get() private val DRAIN_MULT get() = _DRAIN_MULT.get()

View File

@ -46,9 +46,8 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ::ItemJob), IMatterGraphNode, IDroppableContainer { MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ::ItemJob), IMatterGraphNode, IDroppableContainer {
val container = MatteryContainer(this::itemContainerUpdated, 1) val container = MatteryContainer(this::itemContainerUpdated, 1)
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_VALUES) val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_VALUES)
val itemHandler = container.handler(object : MatteryContainerHooks {
private val itemHandler = container.handler(object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean { override fun canInsert(slot: Int, stack: ItemStack): Boolean {
return MatterManager.canDecompose(stack) return MatterManager.canDecompose(stack)
} }
@ -58,8 +57,16 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
}) })
override val droppableContainer: Container override val droppableContainer by ::container
get() = container
init {
exposeItemsGlobally(itemHandler)
exposeEnergyGlobally(energy)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
savetable(::container, INVENTORY_KEY)
savetable(::energy, ENERGY_KEY)
}
// IMatterGraphNode // IMatterGraphNode
override fun onPatternAdded(state: IPatternState) { override fun onPatternAdded(state: IPatternState) {
@ -81,56 +88,22 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
// /IMatterGraphNode // /IMatterGraphNode
private var valid = true
override val matterNode: Graph6Node<IMatterGraphNode> = Graph6Node(this) override val matterNode: Graph6Node<IMatterGraphNode> = Graph6Node(this)
private var resolverNode = LazyOptional.of { this }
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) {
if (cap == ForgeCapabilities.ITEM_HANDLER) return itemHandler.get().cast()
if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast()
}
return super.getCapability(cap, side)
}
override fun invalidateCaps() { override fun invalidateCaps() {
super.invalidateCaps() super.invalidateCaps()
valid = false
itemHandler.invalidate()
resolverNode.invalidate()
matterNode.destroy(::MatterNetworkGraph) matterNode.destroy(::MatterNetworkGraph)
} }
override fun reviveCaps() {
super.reviveCaps()
valid = true
itemHandler.revive()
resolverNode = LazyOptional.of { this }
}
override fun setRemoved() { override fun setRemoved() {
super.setRemoved() super.setRemoved()
matterNode.destroy(::MatterNetworkGraph) matterNode.destroy(::MatterNetworkGraph)
} }
override val defaultDisplayName: Component
get() = MBlocks.MATTER_SCANNER.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterScannerMenu(containerID, inventory, this) return MatterScannerMenu(containerID, inventory, this)
} }
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt.put(INVENTORY_KEY, container.serializeNBT())
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(INVENTORY_KEY, container::deserializeNBT)
}
override fun onJobFinish(job: ItemJob): Status { override fun onJobFinish(job: ItemJob): Status {
val grid = matterNode.graph as MatterNetworkGraph? ?: return Status.FAILURE_WAIT val grid = matterNode.graph as MatterNetworkGraph? ?: return Status.FAILURE_WAIT

View File

@ -16,7 +16,6 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import ru.dbotthepony.mc.otm.menu.matter.PatternStorageMenu import ru.dbotthepony.mc.otm.menu.matter.PatternStorageMenu
import net.minecraft.MethodsReturnNonnullByDefault import net.minecraft.MethodsReturnNonnullByDefault
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel
import net.minecraft.world.Container import net.minecraft.world.Container
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
@ -25,7 +24,6 @@ import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.mc.otm.block.IDroppableContainer import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.matter.* import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.core.collect.iterator import ru.dbotthepony.mc.otm.core.collect.iterator
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
@ -43,10 +41,8 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryDeviceBlockEntity(MBlockEntities.PATTERN_STORAGE, p_155229_, p_155230_), IMatterGraphNode, IPatternStorage, IDroppableContainer { MatteryDeviceBlockEntity(MBlockEntities.PATTERN_STORAGE, p_155229_, p_155230_), IMatterGraphNode, IPatternStorage, IDroppableContainer {
override val matterNode = Graph6Node<IMatterGraphNode>(this) override val matterNode = Graph6Node<IMatterGraphNode>(this)
private val resolverPatterns = LazyOptional.of { this }
private val resolverNode = LazyOptional.of { this }
val patternContainer: MatteryContainer = object : MatteryContainer(this::setChanged, 8) { val container: MatteryContainer = object : MatteryContainer(this::setChanged, 8) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) { override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
val grid = matterNode.graph as MatterNetworkGraph? val grid = matterNode.graph as MatterNetworkGraph?
@ -82,7 +78,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
for (i in 0..7) { for (i in 0..7) {
state = state.setValue( state = state.setValue(
PatternStorageBlock.PATTERN_STORAGE_DISKS_PROPS[i], PatternStorageBlock.PATTERN_STORAGE_DISKS_PROPS[i],
this.patternContainer.getItem(i).getCapability(MatteryCapability.PATTERN).isPresent this.container.getItem(i).getCapability(MatteryCapability.PATTERN).isPresent
) )
} }
@ -91,21 +87,8 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
} }
private val resolverItem = private val itemHandler = container.handler { slot: Int, stack: ItemStack -> stack.getCapability(MatteryCapability.PATTERN).isPresent }
patternContainer.handler { slot: Int, stack: ItemStack -> stack.getCapability(MatteryCapability.PATTERN).isPresent } override val droppableContainer by ::container
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = patternContainer.serializeNBT()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(INVENTORY_KEY, patternContainer::deserializeNBT)
}
override val droppableContainer: Container
get() = patternContainer
override fun setLevel(p_155231_: Level) { override fun setLevel(p_155231_: Level) {
super.setLevel(p_155231_) super.setLevel(p_155231_)
@ -118,34 +101,19 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return this return this
} }
private var valid = true
override fun invalidateCaps() { override fun invalidateCaps() {
super.invalidateCaps() super.invalidateCaps()
valid = false
resolverItem.invalidate()
matterNode.destroy(::MatterNetworkGraph) matterNode.destroy(::MatterNetworkGraph)
} }
override fun reviveCaps() { init {
super.reviveCaps() exposeGlobally(MatteryCapability.PATTERN, this)
valid = true exposeGlobally(MatteryCapability.MATTER_NODE, this)
resolverItem.revive() exposeItemsGlobally(itemHandler)
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> { savetable(::container, INVENTORY_KEY)
if (valid) {
if (cap == MatteryCapability.PATTERN) return resolverPatterns.cast()
if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast()
if (cap == ForgeCapabilities.ITEM_HANDLER) return resolverItem.get().cast()
} }
return super.getCapability(cap, side)
}
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 {
return PatternStorageMenu(containerID, inventory, this) return PatternStorageMenu(containerID, inventory, this)
} }
@ -153,7 +121,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override val patterns: Stream<out IPatternState> get() { override val patterns: Stream<out IPatternState> get() {
val streams = ArrayList<Stream<out IPatternState>>() val streams = ArrayList<Stream<out IPatternState>>()
for (provider in this.patternContainer.iterator(MatteryCapability.PATTERN)) { for (provider in this.container.iterator(MatteryCapability.PATTERN)) {
streams.add(provider.second.patterns) streams.add(provider.second.patterns)
} }
@ -163,7 +131,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override val patternCapacity: Int get() { override val patternCapacity: Int get() {
var stored = 0L var stored = 0L
for ((_, pattern) in this.patternContainer.iterator(MatteryCapability.PATTERN)) for ((_, pattern) in this.container.iterator(MatteryCapability.PATTERN))
stored += pattern.patternCapacity.toLong() stored += pattern.patternCapacity.toLong()
return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt() return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt()
@ -172,7 +140,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override val storedPatterns: Int get() { override val storedPatterns: Int get() {
var stored = 0L var stored = 0L
for ((_, pattern) in this.patternContainer.iterator(MatteryCapability.PATTERN)) for ((_, pattern) in this.container.iterator(MatteryCapability.PATTERN))
stored += pattern.storedPatterns.toLong() stored += pattern.storedPatterns.toLong()
return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt() return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt()
@ -184,7 +152,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
override fun insertPattern(pattern: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus { override fun insertPattern(pattern: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus {
for (pair in this.patternContainer.iterator(MatteryCapability.PATTERN)) { for (pair in this.container.iterator(MatteryCapability.PATTERN)) {
val status = pair.second.insertPattern(pattern, onlyUpdate, simulate) val status = pair.second.insertPattern(pattern, onlyUpdate, simulate)
if (!status.isFailed) { if (!status.isFailed) {
@ -208,8 +176,4 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return PatternInsertFailure return PatternInsertFailure
} }
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.pattern_storage")
}
} }

View File

@ -30,7 +30,7 @@ import ru.dbotthepony.mc.otm.storage.*
class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.DRIVE_RACK, p_155229_, p_155230_) { MatteryPoweredBlockEntity(MBlockEntities.DRIVE_RACK, p_155229_, p_155230_) {
override val energy = WorkerEnergyStorage(this, MachinesConfig.DRIVE_RACK) val energy = WorkerEnergyStorage(this, MachinesConfig.DRIVE_RACK)
val container: MatteryContainer = object : MatteryContainer(this::setChanged, 4) { val container: MatteryContainer = object : MatteryContainer(this::setChanged, 4) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) { override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
@ -52,14 +52,11 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val cell = BasicStorageGraphNode(energy) val cell = BasicStorageGraphNode(energy)
override fun load(nbt: CompoundTag) { init {
super.load(nbt) savetable(::energy, ENERGY_KEY)
nbt.map(INVENTORY_KEY, container::deserializeNBT) savetable(::container, INVENTORY_KEY)
} exposeEnergyGlobally(energy)
exposeGlobally(MatteryCapability.STORAGE_NODE, cell)
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
} }
override fun setLevel(p_155231_: Level) { override fun setLevel(p_155231_: Level) {
@ -74,29 +71,10 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
cell.tickEnergyDemanding() cell.tickEnergyDemanding()
} }
override val defaultDisplayName: Component
get() = MBlocks.DRIVE_RACK.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return DriveRackMenu(containerID, inventory, this) return DriveRackMenu(containerID, inventory, this)
} }
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
return if (cap === MatteryCapability.STORAGE_NODE) {
cell.get().cast()
} else super.getCapability(cap, side)
}
override fun invalidateCaps() {
super.invalidateCaps()
cell.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
cell.revive()
}
override fun setRemoved() { override fun setRemoved() {
super.setRemoved() super.setRemoved()
cell.destroy(level) cell.destroy(level)

View File

@ -45,7 +45,7 @@ class DriveViewerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
} }
} }
override val energy = WorkerEnergyStorage(this, MachinesConfig.DRIVE_VIEWER) val energy = WorkerEnergyStorage(this, MachinesConfig.DRIVE_VIEWER)
val container: MatteryContainer = object : MatteryContainer(this::setChanged, 1) { val container: MatteryContainer = object : MatteryContainer(this::setChanged, 1) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) { override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
@ -69,25 +69,19 @@ class DriveViewerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
} }
} }
override val droppableContainer: Container override val droppableContainer by ::container
get() = container
override val defaultDisplayName: Component init {
get() = MBlocks.DRIVE_VIEWER.name savetable(::energy, ENERGY_KEY)
savetable(::container, INVENTORY_KEY)
exposeEnergyGlobally(energy)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return DriveViewerMenu(containerID, inventory, this) return DriveViewerMenu(containerID, inventory, this)
} }
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(INVENTORY_KEY, container::deserializeNBT)
}
fun tick() { fun tick() {
batteryChargeLoop() batteryChargeLoop()
} }

View File

@ -183,7 +183,12 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.ITEM_MONITOR, p_155229_, p_155230_), MatteryPoweredBlockEntity(MBlockEntities.ITEM_MONITOR, p_155229_, p_155230_),
IStorageEventConsumer<ItemStackWrapper> { IStorageEventConsumer<ItemStackWrapper> {
override val energy = WorkerEnergyStorage(this, MachinesConfig.ITEM_MONITOR) val energy = WorkerEnergyStorage(this, MachinesConfig.ITEM_MONITOR)
init {
exposeEnergyGlobally(energy)
savetable(::energy, ENERGY_KEY)
}
var poweredView: PoweredVirtualComponent<ItemStackWrapper>? = null var poweredView: PoweredVirtualComponent<ItemStackWrapper>? = null
private set private set
@ -201,6 +206,10 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
} }
init {
exposeGlobally(MatteryCapability.STORAGE_NODE, cell)
}
private val settings = HashMap<UUID, ItemMonitorPlayerSettings>() private val settings = HashMap<UUID, ItemMonitorPlayerSettings>()
private val craftingAmount = Object2ObjectArrayMap<Player, Int>() private val craftingAmount = Object2ObjectArrayMap<Player, Int>()
private val lastCraftingRecipe = Object2ObjectArrayMap<Player, CraftingRecipe>() private val lastCraftingRecipe = Object2ObjectArrayMap<Player, CraftingRecipe>()
@ -488,9 +497,6 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
lastCraftingRecipe.clear() lastCraftingRecipe.clear()
} }
override val defaultDisplayName: Component
get() = MBlocks.ITEM_MONITOR.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return ItemMonitorMenu(containerID, inventory, this) return ItemMonitorMenu(containerID, inventory, this)
} }
@ -502,22 +508,6 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
StorageNetworkGraph.discoverFull(this, cell.storageNode) StorageNetworkGraph.discoverFull(this, cell.storageNode)
} }
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
return if (cap === MatteryCapability.STORAGE_NODE) {
cell.get().cast()
} else super.getCapability(cap, side)
}
override fun invalidateCaps() {
super.invalidateCaps()
cell.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
cell.revive()
}
override fun setRemoved() { override fun setRemoved() {
super.setRemoved() super.setRemoved()
cell.destroy(level) cell.destroy(level)

View File

@ -29,6 +29,7 @@ import ru.dbotthepony.mc.otm.config.ServerConfig
import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.math.getCapability import ru.dbotthepony.mc.otm.core.math.getCapability
import ru.dbotthepony.mc.otm.core.math.isPositive import ru.dbotthepony.mc.otm.core.math.isPositive
import ru.dbotthepony.mc.otm.core.math.isZero import ru.dbotthepony.mc.otm.core.math.isZero
@ -77,7 +78,12 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
return StorageBusMenu(containerID, inventory, this) return StorageBusMenu(containerID, inventory, this)
} }
override val energy = WorkerEnergyStorage(this::setChangedLight, MachinesConfig.STORAGE_INTERFACES) val energy = WorkerEnergyStorage(this::setChangedLight, MachinesConfig.STORAGE_INTERFACES)
init {
exposeEnergyGlobally(energy)
savetable(::energy, ENERGY_KEY)
}
val cell: BasicStorageGraphNode = object : BasicStorageGraphNode(energy), GraphNodeListener { val cell: BasicStorageGraphNode = object : BasicStorageGraphNode(energy), GraphNodeListener {
override fun onNeighbour(node: Graph6Node<*>, direction: Direction) { override fun onNeighbour(node: Graph6Node<*>, direction: Direction) {
@ -95,11 +101,20 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
} }
} }
init {
exposeSideless(MatteryCapability.STORAGE_NODE, cell)
exposeAllSidesExcept(RelativeSide.FRONT, MatteryCapability.STORAGE_NODE, cell)
}
val filter = ItemFilter(MAX_FILTERS) { _, _, _ -> val filter = ItemFilter(MAX_FILTERS) { _, _, _ ->
component?.scan() component?.scan()
setChangedLight() setChangedLight()
} }
init {
savetable(::filter, FILTER_KEY)
}
override fun setLevel(p_155231_: Level) { override fun setLevel(p_155231_: Level) {
super.setLevel(p_155231_) super.setLevel(p_155231_)
@ -110,26 +125,6 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
tickOnceServer(this::checkSurroundings) tickOnceServer(this::checkSurroundings)
} }
private var valid = true
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
return if (valid && cap === MatteryCapability.STORAGE_NODE && side != blockState.getValue(BlockRotationFreedom.TWO.property).front) {
cell.get().cast()
} else super.getCapability(cap, side)
}
override fun invalidateCaps() {
super.invalidateCaps()
cell.invalidate()
valid = false
}
override fun reviveCaps() {
super.reviveCaps()
cell.revive()
valid = true
}
private var neighbour: LazyOptional<IItemHandler>? = null private var neighbour: LazyOptional<IItemHandler>? = null
private var component: ItemHandlerComponent? = null private var component: ItemHandlerComponent? = null
@ -142,17 +137,6 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
override fun setRemoved() { override fun setRemoved() {
super.setRemoved() super.setRemoved()
cell.destroy(level) cell.destroy(level)
valid = false
}
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[FILTER_KEY] = filter.serializeNBT()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(FILTER_KEY, filter::deserializeNBT)
} }
fun checkSurroundings() { fun checkSurroundings() {

View File

@ -30,6 +30,7 @@ import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.math.rotationTwo import ru.dbotthepony.mc.otm.core.math.rotationTwo
import ru.dbotthepony.mc.otm.core.math.toIntSafe import ru.dbotthepony.mc.otm.core.math.toIntSafe
import ru.dbotthepony.mc.otm.core.math.unaryMinus import ru.dbotthepony.mc.otm.core.math.unaryMinus
@ -56,7 +57,12 @@ abstract class AbstractStorageImportExport<T>(
blockState: BlockState, blockState: BlockState,
energyValues: ConciseBalanceValues = MachinesConfig.STORAGE_INTERFACES energyValues: ConciseBalanceValues = MachinesConfig.STORAGE_INTERFACES
) : MatteryPoweredBlockEntity(blockType, blockPos, blockState) { ) : MatteryPoweredBlockEntity(blockType, blockPos, blockState) {
final override val energy = WorkerEnergyStorage(this::setChangedLight, energyValues) val energy = WorkerEnergyStorage(::setChangedLight, energyValues)
init {
exposeEnergyGlobally(energy)
savetable(::energy, ENERGY_KEY)
}
val cell: BasicStorageGraphNode = object : BasicStorageGraphNode(energy), GraphNodeListener { val cell: BasicStorageGraphNode = object : BasicStorageGraphNode(energy), GraphNodeListener {
override fun onNeighbour(node: Graph6Node<*>, direction: Direction) { override fun onNeighbour(node: Graph6Node<*>, direction: Direction) {
@ -74,32 +80,24 @@ abstract class AbstractStorageImportExport<T>(
} }
} }
private var valid = true init {
exposeSideless(MatteryCapability.STORAGE_NODE, cell)
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> { exposeAllSidesExcept(RelativeSide.FRONT, MatteryCapability.STORAGE_NODE, cell)
return if (valid && cap === MatteryCapability.STORAGE_NODE && side != blockState.getValue(BlockRotationFreedom.TWO.property).front) {
cell.get().cast()
} else super.getCapability(cap, side)
} }
override fun invalidateCaps() { override fun invalidateCaps() {
super.invalidateCaps() super.invalidateCaps()
cell.invalidate()
target.invalidate() target.invalidate()
valid = false
} }
override fun reviveCaps() { override fun reviveCaps() {
super.reviveCaps() super.reviveCaps()
cell.revive()
target.revive() target.revive()
valid = true
} }
override fun setRemoved() { override fun setRemoved() {
super.setRemoved() super.setRemoved()
cell.destroy(level) cell.destroy(level)
valid = false
} }
override fun setLevel(p_155231_: Level) { override fun setLevel(p_155231_: Level) {
@ -127,14 +125,8 @@ abstract class AbstractStorageImportExport<T>(
abstract val filter: ItemFilter abstract val filter: ItemFilter
override fun saveAdditional(nbt: CompoundTag) { init {
super.saveAdditional(nbt) savetable(::filter, FILTER_KEY)
nbt[FILTER_KEY] = filter.serializeNBT()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(FILTER_KEY, filter::deserializeNBT)
} }
companion object { companion object {
@ -146,9 +138,6 @@ abstract class AbstractStorageImportExport<T>(
class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState)
: AbstractStorageImportExport<IItemHandler>(MBlockEntities.STORAGE_IMPORTER, blockPos, blockState), : AbstractStorageImportExport<IItemHandler>(MBlockEntities.STORAGE_IMPORTER, blockPos, blockState),
IItemHandler { IItemHandler {
override val defaultDisplayName: Component
get() = MACHINE_NAME
override val filter = ItemFilter(MAX_FILTERS) { _, _, _ -> override val filter = ItemFilter(MAX_FILTERS) { _, _, _ ->
setChangedLight() setChangedLight()
} }
@ -165,27 +154,8 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState)
override val targetCapability: Capability<IItemHandler> override val targetCapability: Capability<IItemHandler>
get() = ForgeCapabilities.ITEM_HANDLER get() = ForgeCapabilities.ITEM_HANDLER
private var valid = true init {
private var resolverItemHandler = LazyOptional.of<IItemHandler> { this } front.Cap(ForgeCapabilities.ITEM_HANDLER, this)
override fun invalidateCaps() {
super.invalidateCaps()
resolverItemHandler.invalidate()
valid = false
}
override fun reviveCaps() {
super.reviveCaps()
resolverItemHandler = LazyOptional.of { this }
valid = true
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid && cap == ForgeCapabilities.ITEM_HANDLER && side == blockState.rotationTwo.front) {
return resolverItemHandler.cast()
}
return super.getCapability(cap, side)
} }
override fun getSlots(): Int { override fun getSlots(): Int {

View File

@ -30,18 +30,27 @@ import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.STORAGE_POWER_SUPPLIER, blockPos, blockState) { class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.STORAGE_POWER_SUPPLIER, blockPos, blockState) {
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 {
return StoragePowerSupplierMenu(containerID, inventory, this) return StoragePowerSupplierMenu(containerID, inventory, this)
} }
val cell = BasicStorageGraphNode() val cell = BasicStorageGraphNode()
val energy = WorkerEnergyStorage(this, MachinesConfig.STORAGE_POWER_SUPPLIER)
init {
savetable(::energy, ENERGY_KEY)
exposeEnergyGlobally(energy)
exposeGlobally(MatteryCapability.STORAGE_NODE, cell)
}
var powerPassed = Decimal.ZERO var powerPassed = Decimal.ZERO
private set private set
init {
savetable(::powerPassed, POWER_PASSED_KEY, Decimal::serializeNBT, Decimal.Companion::deserializeNBT)
}
override fun setLevel(p_155231_: Level) { override fun setLevel(p_155231_: Level) {
super.setLevel(p_155231_) super.setLevel(p_155231_)
@ -50,30 +59,9 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState
} }
} }
private var valid = true
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
return if (valid && cap === MatteryCapability.STORAGE_NODE) {
cell.get().cast()
} else super.getCapability(cap, side)
}
override fun invalidateCaps() {
super.invalidateCaps()
cell.invalidate()
valid = false
}
override fun reviveCaps() {
super.reviveCaps()
cell.revive()
valid = true
}
override fun setRemoved() { override fun setRemoved() {
super.setRemoved() super.setRemoved()
cell.destroy(level) cell.destroy(level)
valid = false
} }
fun tick() { fun tick() {
@ -119,20 +107,7 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState
} }
} }
override val energy = WorkerEnergyStorage(this, MachinesConfig.STORAGE_POWER_SUPPLIER)
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[POWER_PASSED_KEY] = powerPassed.serializeNBT()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
powerPassed = nbt.getDecimal(POWER_PASSED_KEY)
}
companion object { companion object {
private val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_POWER_SUPPLIER}")
const val POWER_PASSED_KEY = "powerPassed" const val POWER_PASSED_KEY = "powerPassed"
} }
} }

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.block.entity.tech package ru.dbotthepony.mc.otm.block.entity.tech
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.MenuProvider import net.minecraft.world.MenuProvider
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
@ -21,7 +20,6 @@ import ru.dbotthepony.mc.otm.core.math.defineDecimal
import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MNames import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.core.util.WriteOnce import ru.dbotthepony.mc.otm.core.util.WriteOnce
@ -33,10 +31,7 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return AndroidStationMenu(containerID, inventory, this) return AndroidStationMenu(containerID, inventory, this)
} }
override val defaultDisplayName: Component val energy = object : WorkerEnergyStorage(this@AndroidStationBlockEntity::setChangedLight,
get() = MBlocks.ANDROID_STATION.name
override val energy = object : WorkerEnergyStorage(this@AndroidStationBlockEntity::setChangedLight,
AndroidStationBlockEntity.Companion::CAPACITY, AndroidStationBlockEntity.Companion::CAPACITY,
AndroidStationBlockEntity.Companion::MAX_IO, { null }) { AndroidStationBlockEntity.Companion::MAX_IO, { null }) {
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal { override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
@ -63,11 +58,16 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
} }
private var tickedOnve = false init {
exposeEnergyGlobally(energy)
savetable(::energy, ENERGY_KEY)
}
private var tickedOnce = false
fun tick() { fun tick() {
if (!tickedOnve) { if (!tickedOnce) {
tickedOnve = true tickedOnce = true
if (energy.batteryLevel.isPositive && blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) { if (energy.batteryLevel.isPositive && blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS) level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS)

View File

@ -25,6 +25,7 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerHooks import ru.dbotthepony.mc.otm.container.MatteryContainerHooks
import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.math.facingOne import ru.dbotthepony.mc.otm.core.math.facingOne
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.BESubscribeList import ru.dbotthepony.mc.otm.core.util.BESubscribeList
@ -48,8 +49,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
synchronizer.bool(false, name = "battery$it") synchronizer.bool(false, name = "battery$it")
} }
override val droppableContainer: Container override val droppableContainer by ::container
get() = container
private val itemHandler = container.handler( private val itemHandler = container.handler(
object : MatteryContainerHooks { object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean { override fun canInsert(slot: Int, stack: ItemStack): Boolean {
@ -62,6 +62,11 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
} }
) )
init {
exposeItemsGlobally(itemHandler)
savetable(::container, INVENTORY_KEY)
}
private data class BatteryBankDistribution(val distribution: Array<Decimal>, val maxThroughput: Decimal) private data class BatteryBankDistribution(val distribution: Array<Decimal>, val maxThroughput: Decimal)
private inner class BatteryBankEnergy(override val energyFlow: FlowDirection) : IMatteryEnergyStorage { private inner class BatteryBankEnergy(override val energyFlow: FlowDirection) : IMatteryEnergyStorage {
@ -190,63 +195,19 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
private val energyExtractor = BatteryBankEnergy(FlowDirection.OUTPUT) private val energyExtractor = BatteryBankEnergy(FlowDirection.OUTPUT)
private val energy = BatteryBankEnergy(FlowDirection.BI_DIRECTIONAL) private val energy = BatteryBankEnergy(FlowDirection.BI_DIRECTIONAL)
private var resolverEnergyReceiver = LazyOptional.of { energyReceiver }
private var resolverEnergyExtractor = LazyOptional.of { energyExtractor }
private var resolverEnergy = LazyOptional.of { energy }
private var mekanismResolverEnergyReceiver = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(energyReceiver) } else LazyOptional.empty()
private var mekanismResolverEnergyExtractor = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(energyExtractor) } else LazyOptional.empty()
private var mekanismResolverEnergy = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(energy) } else LazyOptional.empty()
private var resolverItemHandler = LazyOptional.of { itemHandler }
private var valid = true
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
}
override fun load(nbt: CompoundTag) {
container.deserializeNBT(nbt[INVENTORY_KEY])
super.load(nbt)
}
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 {
return BatteryBankMenu(containerID, inventory, this) return BatteryBankMenu(containerID, inventory, this)
} }
override fun invalidateCaps() { init {
super.invalidateCaps() exposeEnergySideless(energy)
valid = false exposeEnergy(RelativeSide.FRONT, energyExtractor)
resolverEnergyReceiver.invalidate()
resolverEnergyExtractor.invalidate()
resolverEnergy.invalidate()
resolverItemHandler.invalidate()
if (isMekanismLoaded) { for (side in RelativeSide.values()) {
mekanismResolverEnergyReceiver.invalidate() if (side != RelativeSide.FRONT) {
mekanismResolverEnergyExtractor.invalidate() exposeEnergy(side, energyReceiver)
mekanismResolverEnergy.invalidate()
} }
} }
override fun reviveCaps() {
super.reviveCaps()
valid = true
resolverEnergyReceiver = LazyOptional.of { energyReceiver }
resolverEnergyExtractor = LazyOptional.of { energyExtractor }
resolverEnergy = LazyOptional.of { energy }
resolverItemHandler = LazyOptional.of { itemHandler }
if (isMekanismLoaded) {
mekanismResolverEnergyReceiver = LazyOptional.of { Mattery2MekanismEnergyWrapper(energyReceiver) }
mekanismResolverEnergyExtractor = LazyOptional.of { Mattery2MekanismEnergyWrapper(energyExtractor) }
mekanismResolverEnergy = LazyOptional.of { Mattery2MekanismEnergyWrapper(energy) }
}
} }
override fun setLevel(p_155231_: Level) { override fun setLevel(p_155231_: Level) {
@ -254,34 +215,6 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
checkSurroundings() checkSurroundings()
} }
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) {
if (cap == MatteryCapability.ENERGY || cap == ForgeCapabilities.ENERGY) {
if (side == null) return resolverEnergy.cast()
if (side == blockState.facingOne)
return resolverEnergyExtractor.cast()
else
return resolverEnergyReceiver.cast()
}
if (cap == MatteryCapability.MEKANISM_ENERGY) {
if (side == null) return mekanismResolverEnergy.cast()
if (side == blockState.facingOne)
return mekanismResolverEnergyExtractor.cast()
else
return mekanismResolverEnergyReceiver.cast()
}
if (cap == ForgeCapabilities.ITEM_HANDLER) {
return resolverItemHandler.cast()
}
}
return super.getCapability(cap,side)
}
private val consumers = object : BESubscribeList<IEnergyStorage>(this@BatteryBankBlockEntity, ForgeCapabilities.ENERGY) { private val consumers = object : BESubscribeList<IEnergyStorage>(this@BatteryBankBlockEntity, ForgeCapabilities.ENERGY) {
override fun test(t: Direction): Boolean { override fun test(t: Direction): Boolean {
return blockState.facingOne == t return blockState.facingOne == t
@ -317,8 +250,6 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
} }
companion object { companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.battery_bank")
const val CAPACITY = 6 * 2 const val CAPACITY = 6 * 2
private val LOGGER = LogManager.getLogger()
} }
} }

View File

@ -23,6 +23,7 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.capability.energy.GeneratorEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.GeneratorEnergyStorage
import ru.dbotthepony.mc.otm.compat.mekanism.Mattery2MekanismEnergyWrapper
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerHooks import ru.dbotthepony.mc.otm.container.MatteryContainerHooks
import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.*
@ -39,19 +40,45 @@ import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.BESubscribeList import ru.dbotthepony.mc.otm.core.util.BESubscribeList
class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.CHEMICAL_GENERATOR, pos, state), IDroppableContainer { class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.CHEMICAL_GENERATOR, pos, state), IDroppableContainer {
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 {
return ChemicalGeneratorMenu(containerID, inventory, this) return ChemicalGeneratorMenu(containerID, inventory, this)
} }
private var valid = true private var valid = true
val container = MatteryContainer(this::setChangedLight, SLOTS) val container = MatteryContainer(this::setChangedLight, SLOTS)
override val droppableContainer: Container override val droppableContainer by ::container
get() = container
val energy = GeneratorEnergyStorage(this::setChangedLight, CAPACITY, THROUGHPUT) val energy = GeneratorEnergyStorage(this::setChangedLight, CAPACITY, THROUGHPUT)
val itemHandler = container.handler(object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
if (slot == SLOT_INPUT)
return ForgeHooks.getBurnTime(stack, null) > 0
if (slot == SLOT_RESIDUE)
return false
return stack.getCapability(ForgeCapabilities.ENERGY).isPresent
}
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
if (slot == SLOT_RESIDUE) return true
return slot == SLOT_BATTERY &&
(!stack.getCapability(ForgeCapabilities.ENERGY).isPresent || stack.getCapability(ForgeCapabilities.ENERGY).resolve().get().receiveEnergy(Int.MAX_VALUE, true) <= 0)
}
})
init {
savetable(::energy, ENERGY_KEY)
exposeGlobally(ForgeCapabilities.ITEM_HANDLER, itemHandler)
exposeGlobally(ForgeCapabilities.ENERGY, energy)
exposeGlobally(MatteryCapability.ENERGY, energy)
if (isMekanismLoaded) {
exposeGlobally(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(energy))
}
}
private val consumers = BESubscribeList(this, ForgeCapabilities.ENERGY) private val consumers = BESubscribeList(this, ForgeCapabilities.ENERGY)
fun checkSurroundings() = consumers.update() fun checkSurroundings() = consumers.update()
@ -61,16 +88,6 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe
checkFuelSlot = true checkFuelSlot = true
} }
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid && (cap == MatteryCapability.ENERGY || cap == ForgeCapabilities.ENERGY) && side !== blockState.facingOne)
return energy.resolver.cast()
if (valid && cap == ForgeCapabilities.ITEM_HANDLER)
return itemHandler.get().cast()
return super.getCapability(cap, side)
}
override fun invalidateCaps() { override fun invalidateCaps() {
super.invalidateCaps() super.invalidateCaps()
itemHandler.invalidate() itemHandler.invalidate()
@ -108,25 +125,6 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe
workTicksTotal = nbt.getInt(WORK_TICKS_TOTAL_KEY) workTicksTotal = nbt.getInt(WORK_TICKS_TOTAL_KEY)
} }
val itemHandler = container.handler(object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
if (slot == SLOT_INPUT)
return ForgeHooks.getBurnTime(stack, null) > 0
if (slot == SLOT_RESIDUE)
return false
return stack.getCapability(ForgeCapabilities.ENERGY).isPresent
}
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
if (slot == SLOT_RESIDUE) return true
return slot == SLOT_BATTERY &&
(!stack.getCapability(ForgeCapabilities.ENERGY).isPresent || stack.getCapability(ForgeCapabilities.ENERGY).resolve().get().receiveEnergy(Int.MAX_VALUE, true) <= 0)
}
})
override fun setBlockState(p_155251_: BlockState) { override fun setBlockState(p_155251_: BlockState) {
super.setBlockState(p_155251_) super.setBlockState(p_155251_)
@ -212,7 +210,6 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe
private val THROUGHPUT get() = _THROUGHPUT.get() private val THROUGHPUT get() = _THROUGHPUT.get()
private val GENERATION_SPEED get() = _GENERATION_SPEED.get() private val GENERATION_SPEED get() = _GENERATION_SPEED.get()
private val CAPACITY get() = _CAPACITY.get() private val CAPACITY get() = _CAPACITY.get()
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.chemical_generator")
private var _THROUGHPUT: DecimalConfigValue by WriteOnce() private var _THROUGHPUT: DecimalConfigValue by WriteOnce()
private var _GENERATION_SPEED: DecimalConfigValue by WriteOnce() private var _GENERATION_SPEED: DecimalConfigValue by WriteOnce()

View File

@ -21,16 +21,16 @@ class CobblerBlockEntity(blockPos: BlockPos, blockState: BlockState)
return CobblerMenu(containerID, inventory, this) return CobblerMenu(containerID, inventory, this)
} }
override val energy = null
override val droppableContainer = MatteryContainer(this::itemContainerUpdated, CONTAINER_SIZE) override val droppableContainer = MatteryContainer(this::itemContainerUpdated, CONTAINER_SIZE)
val handler = StaticCap(ForgeCapabilities.ITEM_HANDLER, INVENTORY_KEY, droppableContainer.handler(object : MatteryContainerHooks { val handler = droppableContainer.handler(object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean { override fun canInsert(slot: Int, stack: ItemStack): Boolean {
return false return false
} }
})) })
init { init {
exposeItemsGlobally(handler)
savetable(::droppableContainer, INVENTORY_KEY) savetable(::droppableContainer, INVENTORY_KEY)
} }

View File

@ -345,7 +345,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
outputCapability.update((-blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION))::equals) outputCapability.update((-blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION))::equals)
} }
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> { override fun <T : Any> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (side == null || isRemoved) if (side == null || isRemoved)
return super.getCapability(cap, side) return super.getCapability(cap, side)

View File

@ -95,49 +95,16 @@ class EnergyServoBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
get() = container[SLOT_CHARGE].energy?.maxEnergyStoredMattery ?: container[SLOT_DISCHARGE].energy?.maxEnergyStoredMattery ?: Decimal.ZERO get() = container[SLOT_CHARGE].energy?.maxEnergyStoredMattery ?: container[SLOT_DISCHARGE].energy?.maxEnergyStoredMattery ?: Decimal.ZERO
} }
private var resolverEnergy = LazyOptional.of { energy } init {
private var valid = true exposeEnergyGlobally(energy)
exposeItemsGlobally(itemHandler)
override fun invalidateCaps() { savetable(::container, INVENTORY_KEY)
super.invalidateCaps()
valid = false
resolverEnergy.invalidate()
itemHandler.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
resolverEnergy = LazyOptional.of { energy }
itemHandler.revive()
} }
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return EnergyServoMenu(containerID, inventory, this) return EnergyServoMenu(containerID, inventory, this)
} }
override fun <T : Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) {
when (cap) {
MatteryCapability.ENERGY, ForgeCapabilities.ENERGY -> return resolverEnergy.cast()
ForgeCapabilities.ITEM_HANDLER -> return itemHandler.get().cast()
}
}
return super.getCapability(cap, side)
}
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(INVENTORY_KEY, container::deserializeNBT)
}
fun tick() { fun tick() {
if (redstoneControl.isBlockedByRedstone) if (redstoneControl.isBlockedByRedstone)
return return

View File

@ -38,7 +38,7 @@ class PlatePressBlockEntity(
p_155230_: BlockState p_155230_: BlockState
) : MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ::ItemJob), IDroppableContainer { ) : MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ::ItemJob), IDroppableContainer {
val container = MatteryContainer(this::setChangedLight, 2) val container = MatteryContainer(this::setChangedLight, 2)
override val energy = WorkerEnergyStorage(this::setChangedLight, MachinesConfig.PLATE_PRESS) val energy = WorkerEnergyStorage(this::setChangedLight, MachinesConfig.PLATE_PRESS)
var experience = 0.0 var experience = 0.0
@ -51,8 +51,7 @@ class PlatePressBlockEntity(
} }
} }
override val droppableContainer: Container override val droppableContainer by ::container
get() = container
val itemHandler = container.handler(object : MatteryContainerHooks { val itemHandler = container.handler(object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean { override fun canInsert(slot: Int, stack: ItemStack): Boolean {
return slot != SLOT_OUTPUT return slot != SLOT_OUTPUT
@ -63,38 +62,12 @@ class PlatePressBlockEntity(
} }
}) })
override fun invalidateCaps() { init {
super.invalidateCaps() savetable(::energy, ENERGY_KEY)
itemHandler.invalidate() savetable(::container, INVENTORY_KEY)
savetableDouble(::experience)
} }
override fun reviveCaps() {
super.reviveCaps()
itemHandler.revive()
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (cap == ForgeCapabilities.ITEM_HANDLER)
return itemHandler.get().cast()
return super.getCapability(cap, side)
}
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
nbt["experience"] = experience
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(INVENTORY_KEY, container::deserializeNBT)
experience = nbt.getDouble("experience")
}
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 {
return PlatePressMenu(containerID, inventory, this) return PlatePressMenu(containerID, inventory, this)
} }
@ -122,7 +95,6 @@ class PlatePressBlockEntity(
companion object { companion object {
private val BASELINE_CONSUMPTION = Decimal(15) private val BASELINE_CONSUMPTION = Decimal(15)
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.plate_press")
const val SLOT_INPUT = 0 const val SLOT_INPUT = 0
const val SLOT_OUTPUT = 1 const val SLOT_OUTPUT = 1
} }

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.block.matter package ru.dbotthepony.mc.otm.block.matter
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.world.Containers import net.minecraft.world.Containers
import net.minecraft.world.item.context.BlockPlaceContext import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.BlockGetter import net.minecraft.world.level.BlockGetter
@ -18,7 +17,6 @@ import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.matter.PatternStorageBlockEntity import ru.dbotthepony.mc.otm.block.entity.matter.PatternStorageBlockEntity
import ru.dbotthepony.mc.otm.block.getShapeForEachState import ru.dbotthepony.mc.otm.block.getShapeForEachState
import ru.dbotthepony.mc.otm.core.get import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.math.facingOne
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes
class PatternStorageBlock : RotatableMatteryBlock(), EntityBlock { class PatternStorageBlock : RotatableMatteryBlock(), EntityBlock {
@ -51,7 +49,7 @@ class PatternStorageBlock : RotatableMatteryBlock(), EntityBlock {
val blockentity = level.getBlockEntity(blockPos) val blockentity = level.getBlockEntity(blockPos)
if (blockentity is PatternStorageBlockEntity) { if (blockentity is PatternStorageBlockEntity) {
Containers.dropContents(level, blockPos, blockentity.patternContainer) Containers.dropContents(level, blockPos, blockentity.container)
level.updateNeighbourForOutputSignal(blockPos, this) level.updateNeighbourForOutputSignal(blockPos, this)
} }
} }

View File

@ -134,7 +134,7 @@ val ICapabilityProvider.energy: IEnergyStorage? get() {
} }
/** /**
* Shortcut for getting [IMatteryEnergyStorage], including wrappers for it * Shortcut for getting sideless [IMatteryEnergyStorage], including wrappers for it
*/ */
val ICapabilityProvider.matteryEnergy: IMatteryEnergyStorage? get() { val ICapabilityProvider.matteryEnergy: IMatteryEnergyStorage? get() {
val mattery = getCapability(MatteryCapability.ENERGY) val mattery = getCapability(MatteryCapability.ENERGY)

View File

@ -30,7 +30,7 @@ sealed class BlockEnergyStorageImpl(
private val maxBatteryLevelProvider: () -> Decimal, private val maxBatteryLevelProvider: () -> Decimal,
private val maxInputProvider: () -> Decimal?, private val maxInputProvider: () -> Decimal?,
private val maxOutputProvider: () -> Decimal?, private val maxOutputProvider: () -> Decimal?,
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag>, IEnergyStorageImpl { ) : IMatteryEnergyStorage, INBTSerializable<CompoundTag?>, IEnergyStorageImpl {
constructor( constructor(
listener: () -> Unit, listener: () -> Unit,
direction: FlowDirection, direction: FlowDirection,
@ -139,7 +139,8 @@ sealed class BlockEnergyStorageImpl(
return tag return tag
} }
override fun deserializeNBT(nbt: CompoundTag) { override fun deserializeNBT(nbt: CompoundTag?) {
if (nbt == null) return
batteryLevel = nbt.map(ENERGY_STORED_KEY, Decimal.Companion::deserializeNBT) ?: Decimal.ZERO batteryLevel = nbt.map(ENERGY_STORED_KEY, Decimal.Companion::deserializeNBT) ?: Decimal.ZERO
maxBatteryLevelStorage = nbt.mapIf(ENERGY_STORED_MAX_KEY, Decimal.Companion::deserializeNBT) maxBatteryLevelStorage = nbt.mapIf(ENERGY_STORED_MAX_KEY, Decimal.Companion::deserializeNBT)
maxInputStorage = nbt.mapIf(MAX_INPUT_KEY, Decimal.Companion::deserializeNBT) maxInputStorage = nbt.mapIf(MAX_INPUT_KEY, Decimal.Companion::deserializeNBT)

View File

@ -15,7 +15,7 @@ open class MatterStorageImpl @JvmOverloads constructor(
protected val maxStoredMatterSupplier: () -> Decimal, protected val maxStoredMatterSupplier: () -> Decimal,
protected val maxReceiveSupplier: () -> Decimal? = { null }, protected val maxReceiveSupplier: () -> Decimal? = { null },
protected val maxExtractSupplier: () -> Decimal? = maxReceiveSupplier protected val maxExtractSupplier: () -> Decimal? = maxReceiveSupplier
) : IMatterStorage, INBTSerializable<CompoundTag> { ) : IMatterStorage, INBTSerializable<CompoundTag?> {
constructor( constructor(
listener: Runnable?, listener: Runnable?,
direction: FlowDirection, direction: FlowDirection,
@ -123,7 +123,8 @@ open class MatterStorageImpl @JvmOverloads constructor(
} }
} }
override fun deserializeNBT(tag: CompoundTag) { override fun deserializeNBT(tag: CompoundTag?) {
if (tag == null) return
storedMatter = Decimal.deserializeNBT(tag["stored"]) storedMatter = Decimal.deserializeNBT(tag["stored"])
//maxStoredMatter = ImpreciseFraction.deserializeNBT(tag["max_storage"]) //maxStoredMatter = ImpreciseFraction.deserializeNBT(tag["max_storage"])
//maxReceive = if (tag.contains("max_receive")) ImpreciseFraction.deserializeNBT(tag["max_receive"]) else null //maxReceive = if (tag.contains("max_receive")) ImpreciseFraction.deserializeNBT(tag["max_receive"]) else null

View File

@ -101,7 +101,7 @@ fun interface ItemFilterFullCallback {
class ItemFilter( class ItemFilter(
val size: Int, val size: Int,
private val modified: ItemFilterFullCallback? = null private val modified: ItemFilterFullCallback? = null
) : INBTSerializable<CompoundTag> { ) : INBTSerializable<CompoundTag?> {
constructor(size: Int, modified: ItemFilterCallback?) : constructor(size: Int, modified: ItemFilterCallback?) :
this(size, this(size,
modified?.let { modified?.let {

View File

@ -251,6 +251,22 @@ inline fun <T> MutableList<out Reference<out T>>.forValidRefs(fn: (T) -> Unit) {
} }
} }
inline fun <T> MutableList<out Reference<out T>>.forValidRefsBreak(fn: (T) -> Boolean) {
val iterator = listIterator()
for (value in iterator) {
val get = value.get()
if (get == null) {
iterator.remove()
} else {
if (fn.invoke(get)) {
break
}
}
}
}
val ComponentContents.key: String val ComponentContents.key: String
get() = (this as? TranslatableContents ?: throw ClassCastException("$this is not a TranslatableContents")).key get() = (this as? TranslatableContents ?: throw ClassCastException("$this is not a TranslatableContents")).key

View File

@ -6,6 +6,7 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
import net.minecraft.world.SimpleContainer import net.minecraft.world.SimpleContainer
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
abstract class MatteryPoweredMenu protected constructor( abstract class MatteryPoweredMenu protected constructor(
@ -14,16 +15,14 @@ abstract class MatteryPoweredMenu protected constructor(
inventory: Inventory, inventory: Inventory,
tile: MatteryPoweredBlockEntity? = null tile: MatteryPoweredBlockEntity? = null
) : MatteryMenu(menuType, containerID, inventory, tile) { ) : MatteryMenu(menuType, containerID, inventory, tile) {
val powerWidget: LevelGaugeWidget val powerWidget = LevelGaugeWidget(this, tile?.matteryEnergy)
val batterySlot: BatterySlot val batterySlot: BatterySlot
val redstone = EnumInputWithFeedback(this, RedstoneSetting::class.java) val redstone = EnumInputWithFeedback(this, RedstoneSetting::class.java)
init { init {
if (tile == null) { if (tile == null) {
powerWidget = LevelGaugeWidget(this)
batterySlot = BatterySlot(SimpleContainer(1), 0) batterySlot = BatterySlot(SimpleContainer(1), 0)
} else { } else {
powerWidget = LevelGaugeWidget(this, tile.energy)
batterySlot = BatterySlot(tile.batteryContainer, 0) batterySlot = BatterySlot(tile.batteryContainer, 0)
redstone.with(tile.redstoneControl::redstoneSetting) redstone.with(tile.redstoneControl::redstoneSetting)
} }

View File

@ -35,7 +35,7 @@ class PatternStorageMenu @JvmOverloads constructor(
}) })
} }
val patterns = tile?.patternContainer ?: SimpleContainer(2 * 4) val patterns = tile?.container ?: SimpleContainer(2 * 4)
storageSlots = ImmutableList(2 * 4) { storageSlots = ImmutableList(2 * 4) {
PatternSlot(patterns, it) PatternSlot(patterns, it)