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.providers.nbt.ContextNbtProvider
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
@ -36,13 +37,13 @@ fun TileNbtCopy(source: String, strategy: CopyNbtFunction.MergeStrategy = CopyNb
}
private val basicTags = arrayOf(
TileNbtCopy(MatteryDeviceBlockEntity.REDSTONE_CONTROL_KEY),
TileNbtCopy(MatteryBlockEntity.REDSTONE_CONTROL_KEY),
)
private val poweredTags = arrayOf(
*basicTags,
TileNbtCopy(MatteryDeviceBlockEntity.ENERGY_KEY),
TileNbtCopy(MatteryDeviceBlockEntity.BATTERY_KEY),
TileNbtCopy(MatteryBlockEntity.ENERGY_KEY),
TileNbtCopy(MatteryBlockEntity.BATTERY_KEY),
)
private val workerTags = arrayOf(
@ -53,7 +54,7 @@ private val workerTags = arrayOf(
private val poweredMatterWorker = arrayOf(
*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 */) {

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 ru.dbotthepony.mc.otm.block.entity.tech.ChemicalGeneratorBlockEntity
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.MatteryDeviceBlockEntity.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.ENERGY_KEY
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.MATTER_STORAGE_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.matter.MatterBottlerBlockEntity
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
import com.google.common.collect.ImmutableSet
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
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.ReferenceArraySet
import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.SectionPos
import net.minecraft.nbt.ByteTag
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.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
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.LevelEvent
import net.minecraftforge.event.server.ServerStoppingEvent
import net.minecraftforge.items.IItemHandler
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.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.forValidRefsBreak
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.math.BlockRotation
import ru.dbotthepony.mc.otm.core.math.RelativeSide
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.FieldSynchronizer
import ru.dbotthepony.mc.otm.network.WorldNetworkChannel
import ru.dbotthepony.mc.otm.oncePre
import ru.dbotthepony.mc.otm.onceServer
import java.lang.ref.WeakReference
import java.util.Collections
import java.util.EnumMap
import java.util.WeakHashMap
import kotlin.properties.ReadWriteProperty
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]
}
// 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> {
return StaticCap(MatteryCapability.ENERGY, "energy", capability).alias(ForgeCapabilities.ENERGY)
protected fun <T : Any> exposeAllSidesExcept(side: RelativeSide, capability: Capability<T>, value: T) {
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> {
private val types = ReferenceArraySet<Capability<in T>>()
protected var valid = true
abstract val capability: T
protected fun isSidelessExposed(capability: Capability<*>): Boolean {
return sidelessCaps.containsKey(capability)
}
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
override fun getValue(thisRef: Any?, property: KProperty<*>): LazyOptional<T> {
if (value == null)
value = if (valid) LazyOptional.of { capability } else LazyOptional.empty()
if (value == null) {
value = LazyOptional.of { capability }
}
return value!!
}
@ -94,205 +329,89 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
this.value = value
}
}
private set
init {
check(!caps.values.any { it.name == name }) { "Already has capability with name $name!" }
check(!caps.containsKey(type)) { "Already has capability with type $type!" }
caps[type] = this
types.add(type)
}
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()
fun remove() {
if (!isRemoved) {
isRemoved = true
val removed = caps.remove(type)
check(removed == this) { "$removed != $this" }
optional.invalidate()
}
}
override fun deserializeNBT(nbt: CompoundTag) {
var sides = 0
if (nbt.contains("sides")) {
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) {
fun close() {
if (!isRemoved && isExposed) {
isExposed = false
optional.invalidate()
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() {
if (valid) {
for ((_, v) in exposedSides)
v.invalidate()
if (!isRemoved && isValid) {
isValid = false
optional.invalidate()
valid = false
setChanged()
}
}
fun revive() {
if (!valid) {
for ((i, pair) in exposedSides.withIndex())
if (pair.first)
exposedSides[i] = true to LazyOptional.of { capability }
if (!isRemoved && !isValid) {
isValid = true
if (isExposed) {
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
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
return caps[cap]?.get(side)?.cast() ?: super.getCapability(cap, side)
return sidelessCaps[cap]?.optional?.cast() ?: super.getCapability(cap, side)
}
override fun invalidateCaps() {
super.invalidateCaps()
for (cap in caps.values)
cap.invalidate()
for (side in sides.values)
side.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
for (cap in caps.values)
cap.revive()
for (side in sides.values)
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)
@ -304,7 +423,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
/**
* 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(!savetables1.any { it.name == name }) { "Already has save field with name $name" }
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
*/
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(!savetables1.any { it.name == name }) { "Already has save field with name $name" }
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
*/
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)
}
/**
* 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)
}
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) {
super.saveAdditional(nbt)
if (caps.isNotEmpty()) {
nbt["Capabilities"] = CompoundTag().also {
for (cap in caps.values) {
it[cap.name] = cap.serializeNBT()
if (_sides.values.any { !it.isEmpty }) {
nbt["Sides"] = CompoundTag().also {
for (side in _sides.values) {
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) {
super.load(nbt)
if (nbt.contains("Capabilities")) {
@Suppress("name_shadowing")
val nbt = nbt.getCompound("Capabilities")
if (nbt.contains("Sides")) {
val tag = nbt.getCompound("Sides")
for (cap in caps.values) {
if (nbt.contains(cap.name)) {
cap.deserializeNBT(nbt.getCompound(cap.name))
for (side in _sides.values) {
if (side.side.name in tag) {
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)) {
(data.deserialize as (Any, Tag) -> Unit).invoke(data.property.get(), value)
} 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)) {
(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.TooltipFlag
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.state.BlockState
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
abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(p_155228_, p_155229_, p_155230_) {
abstract val energy: BlockEnergyStorageImpl?
private var valid = true
val batteryContainer = MatteryContainer(this::setChangedLight, 1)
val batteryContainer = MatteryContainer(::setChangedLight, 1)
init {
savetable(::batteryContainer, BATTERY_KEY)
}
protected fun batteryChargeLoop() {
val energy = matteryEnergy
if (energy == null || !batteryContainer.any { !it.isEmpty })
return
var demand = energy!!.receiveEnergy(energy!!.missingPower, true)
var demand = energy.receiveEnergy(energy.missingPower, true)
if (demand.isZero) return
for (stack in batteryContainer) {
if (!stack.isEmpty) {
stack.getCapability(ForgeCapabilities.ENERGY).ifPresentK {
val diff = it.extractEnergy(demand, false)
energy!!.receiveEnergy(diff, false)
energy.receiveEnergy(diff, false)
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 {
fun appendHoverText(itemStack: ItemStack, blockGetter: BlockGetter?, tooltips: MutableList<Component>, flag: TooltipFlag) {
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.block.Block
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.math.Decimal
import ru.dbotthepony.mc.otm.core.math.getDecimal
@ -254,10 +255,7 @@ abstract class MatteryWorkerBlockEntity<JobType : MatteryWorkerBlockEntity.Job>(
errorTicksAnim = 0
idleTicksAnim++
if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(
WorkerState.WORKER_STATE
) != WorkerState.IDLE
) {
if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.IDLE) {
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
val energy = matteryEnergy
while (!isIdling && weakGreaterThan(availableTicks, 0.0) && throttleTicks <= 0) {
if (redstoneControl.isBlockedByRedstone) {
@ -288,7 +287,7 @@ abstract class MatteryWorkerBlockEntity<JobType : MatteryWorkerBlockEntity.Job>(
currentJob = job
}
if (!currentJob.powerUsage.isZero && (energy == null || energy!!.batteryLevel.isZero)) {
if (!currentJob.powerUsage.isZero && (energy == null || energy.batteryLevel.isZero)) {
idleReason = IdleReason.POWER
isIdling = true
idleTicksAnim++

View File

@ -95,35 +95,19 @@ class CargoCrateBlockEntity(
}
}
override fun invalidateCaps() {
super.invalidateCaps()
handler.invalidate()
}
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)
init {
exposeItemsGlobally(handler)
savetable(::container, INVENTORY_KEY)
}
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
lootTable?.let { nbt[LOOT_TABLE_KEY] = it.toString() }
lootTableSeed?.let { nbt[LOOT_TABLE_SEED_KEY] = it }
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
container.deserializeNBT(nbt[INVENTORY_KEY])
lootTable = nbt.map(LOOT_TABLE_KEY) { it: StringTag -> ResourceLocation.tryParse(it.asString) }
lootTableSeed = (nbt[LOOT_TABLE_SEED_KEY] as LongTag?)?.asLong
}

View File

@ -49,8 +49,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, p_155229_, p_155230_), IMatterGraphNode, IDroppableContainer {
override val matterNode = Graph6Node<IMatterGraphNode>(this)
private val resolverNode = LazyOptional.of { this }
override val energy = WorkerEnergyStorage(this, ENERGY_VALUES)
val energy = WorkerEnergyStorage(this, ENERGY_VALUES)
var isBottling: Boolean = true
set(value) {
@ -98,8 +97,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
}
override val droppableContainer: Container
get() = container
override val droppableContainer by ::container
val itemHandler = container.handler(object : MatteryContainerHooks {
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 lastWorkStack: ItemStack? = null
@ -139,61 +150,10 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
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 {
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 {
val lastWorkStack = lastWorkStack ?: return 0f
val initialCapacity = initialCapacity ?: return 0f

View File

@ -38,7 +38,6 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
private set
override val matterNode = Graph6Node<IMatterGraphNode>(this)
private val resolverNode = LazyOptional.of { this }
override val canSetMatterLevel: Boolean
get() = false
@ -133,8 +132,6 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
override val matterFlow: FlowDirection
get() = FlowDirection.BI_DIRECTIONAL
private var resolver = LazyOptional.of { this }
val container = object : MatteryContainer(this::setChangedLight, BatteryBankBlockEntity.CAPACITY) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old)
@ -147,48 +144,18 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
synchronizer.bool(false, name = "capacitor$it")
}
override val droppableContainer: Container
get() = container
override val defaultDisplayName: Component
get() = MACHINE_NAME
override val droppableContainer by ::container
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)
init {
savetable(::container, INVENTORY_KEY)
exposeGlobally(MatteryCapability.MATTER, this)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
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() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
@ -204,8 +171,4 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
override fun getMatterHandler(): IMatterStorage {
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)
private var valid = true
val energy = WorkerEnergyStorage(this, ENERGY_VALUES)
init {
exposeEnergyGlobally(energy)
savetable(::energy, ENERGY_KEY)
}
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 }
private var resolverNode = LazyOptional.of { this }
init {
exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
savetable(::matter, MATTER_STORAGE_KEY)
}
// вход, выход
val container = MatteryContainer(this::setChangedLight, 3)
override val droppableContainer by ::container
override val droppableContainer: Container
get() = container
private val itemHandler = LazyOptional.of<IItemHandler> {
container.handler(object : MatteryContainerHooks {
val itemHandler = container.handler(object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
return slot == INPUT_SLOT && MatterManager.canDecompose(stack)
}
@ -155,49 +160,16 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
return slot != INPUT_SLOT
}
})
}
override val defaultDisplayName: Component
get() = MBlocks.MATTER_DECOMPOSER.name
init {
exposeItemsGlobally(itemHandler)
savetable(::container, INVENTORY_KEY)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
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 {
if (job.toDust) {
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)
}
private var valid = true
override fun invalidateCaps() {
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)
init {
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeGlobally(MatteryCapability.TASK, this)
}
override fun setLevel(p_155231_: Level) {

View File

@ -82,12 +82,9 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
val container = MatteryContainer(this::itemContainerUpdated, 1)
override val droppableContainer: Container
get() = container
override val droppableContainer by ::container
override val matterNode = Graph6Node<IMatterGraphNode>(this)
private var resolverNode = LazyOptional.of { this }
private var valid = true
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_CONFIG)
val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_CONFIG)
override fun getMatterHandler(): IMatterStorage {
return matter
@ -103,18 +100,14 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
}
})
override fun invalidateCaps() {
super.invalidateCaps()
matter.invalidate()
itemHandler.invalidate()
resolverNode.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
matter.revive()
itemHandler.revive()
resolverNode = LazyOptional.of { this }
init {
exposeItemsGlobally(itemHandler)
exposeEnergyGlobally(energy)
exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
savetable(::energy, ENERGY_KEY)
savetable(::container, INVENTORY_KEY)
savetable(::matter, MATTER_STORAGE_KEY)
}
override fun setRemoved() {
@ -129,33 +122,6 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
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 {
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)
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)
private val itemHandler = container.handler(MatteryContainerHandler.OnlyOut)
val itemHandler = container.handler(MatteryContainerHandler.OnlyOut)
override val droppableContainer by ::container
override val defaultDisplayName: Component
get() = MBlocks.MATTER_REPLICATOR.name
init {
exposeEnergyGlobally(energy)
exposeItemsGlobally(itemHandler)
exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
override val droppableContainer: Container
get() = container
savetable(::energy, ENERGY_KEY)
savetable(::matter, MATTER_STORAGE_KEY)
savetable(::container, INVENTORY_KEY)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterReplicatorMenu(containerID, inventory, this)
@ -270,41 +269,6 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
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 {
private val BASE_CONSUMPTION get() = _BASE_CONSUMPTION.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 {
val container = MatteryContainer(this::itemContainerUpdated, 1)
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_VALUES)
private val itemHandler = container.handler(object : MatteryContainerHooks {
val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_VALUES)
val itemHandler = container.handler(object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
return MatterManager.canDecompose(stack)
}
@ -58,8 +57,16 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
})
override val droppableContainer: Container
get() = container
override val droppableContainer by ::container
init {
exposeItemsGlobally(itemHandler)
exposeEnergyGlobally(energy)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
savetable(::container, INVENTORY_KEY)
savetable(::energy, ENERGY_KEY)
}
// IMatterGraphNode
override fun onPatternAdded(state: IPatternState) {
@ -81,56 +88,22 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
// /IMatterGraphNode
private var valid = true
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() {
super.invalidateCaps()
valid = false
itemHandler.invalidate()
resolverNode.invalidate()
matterNode.destroy(::MatterNetworkGraph)
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
itemHandler.revive()
resolverNode = LazyOptional.of { this }
}
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
}
override val defaultDisplayName: Component
get() = MBlocks.MATTER_SCANNER.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
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 {
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 net.minecraft.MethodsReturnNonnullByDefault
import net.minecraft.core.Direction
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.Container
import net.minecraft.world.level.Level
@ -25,7 +24,6 @@ import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.mc.otm.block.IDroppableContainer
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.core.collect.iterator
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 {
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) {
val grid = matterNode.graph as MatterNetworkGraph?
@ -82,7 +78,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
for (i in 0..7) {
state = state.setValue(
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 =
patternContainer.handler { slot: Int, stack: ItemStack -> stack.getCapability(MatteryCapability.PATTERN).isPresent }
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
private val itemHandler = container.handler { slot: Int, stack: ItemStack -> stack.getCapability(MatteryCapability.PATTERN).isPresent }
override val droppableContainer by ::container
override fun setLevel(p_155231_: Level) {
super.setLevel(p_155231_)
@ -118,34 +101,19 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return this
}
private var valid = true
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
resolverItem.invalidate()
matterNode.destroy(::MatterNetworkGraph)
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
resolverItem.revive()
}
init {
exposeGlobally(MatteryCapability.PATTERN, this)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeItemsGlobally(itemHandler)
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
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()
savetable(::container, INVENTORY_KEY)
}
return super.getCapability(cap, side)
}
override val defaultDisplayName: Component
get() = MACHINE_NAME
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return PatternStorageMenu(containerID, inventory, this)
}
@ -153,7 +121,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override val patterns: Stream<out IPatternState> get() {
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)
}
@ -163,7 +131,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override val patternCapacity: Int get() {
var stored = 0L
for ((_, pattern) in this.patternContainer.iterator(MatteryCapability.PATTERN))
for ((_, pattern) in this.container.iterator(MatteryCapability.PATTERN))
stored += pattern.patternCapacity.toLong()
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() {
var stored = 0L
for ((_, pattern) in this.patternContainer.iterator(MatteryCapability.PATTERN))
for ((_, pattern) in this.container.iterator(MatteryCapability.PATTERN))
stored += pattern.storedPatterns.toLong()
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 {
for (pair in this.patternContainer.iterator(MatteryCapability.PATTERN)) {
for (pair in this.container.iterator(MatteryCapability.PATTERN)) {
val status = pair.second.insertPattern(pattern, onlyUpdate, simulate)
if (!status.isFailed) {
@ -208,8 +176,4 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
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) :
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) {
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)
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.map(INVENTORY_KEY, container::deserializeNBT)
}
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt[INVENTORY_KEY] = container.serializeNBT()
init {
savetable(::energy, ENERGY_KEY)
savetable(::container, INVENTORY_KEY)
exposeEnergyGlobally(energy)
exposeGlobally(MatteryCapability.STORAGE_NODE, cell)
}
override fun setLevel(p_155231_: Level) {
@ -74,29 +71,10 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
cell.tickEnergyDemanding()
}
override val defaultDisplayName: Component
get() = MBlocks.DRIVE_RACK.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
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() {
super.setRemoved()
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) {
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
get() = container
override val defaultDisplayName: Component
get() = MBlocks.DRIVE_VIEWER.name
override val droppableContainer by ::container
init {
savetable(::energy, ENERGY_KEY)
savetable(::container, INVENTORY_KEY)
exposeEnergyGlobally(energy)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
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() {
batteryChargeLoop()
}

View File

@ -183,7 +183,12 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.ITEM_MONITOR, p_155229_, p_155230_),
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
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 craftingAmount = Object2ObjectArrayMap<Player, Int>()
private val lastCraftingRecipe = Object2ObjectArrayMap<Player, CraftingRecipe>()
@ -488,9 +497,6 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
lastCraftingRecipe.clear()
}
override val defaultDisplayName: Component
get() = MBlocks.ITEM_MONITOR.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return ItemMonitorMenu(containerID, inventory, this)
}
@ -502,22 +508,6 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
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() {
super.setRemoved()
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.core.*
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.isPositive
import ru.dbotthepony.mc.otm.core.math.isZero
@ -77,7 +78,12 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
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 {
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) { _, _, _ ->
component?.scan()
setChangedLight()
}
init {
savetable(::filter, FILTER_KEY)
}
override fun setLevel(p_155231_: Level) {
super.setLevel(p_155231_)
@ -110,26 +125,6 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
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 component: ItemHandlerComponent? = null
@ -142,17 +137,6 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
override fun setRemoved() {
super.setRemoved()
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() {

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.math.BlockRotationFreedom
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.toIntSafe
import ru.dbotthepony.mc.otm.core.math.unaryMinus
@ -56,7 +57,12 @@ abstract class AbstractStorageImportExport<T>(
blockState: BlockState,
energyValues: ConciseBalanceValues = MachinesConfig.STORAGE_INTERFACES
) : 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 {
override fun onNeighbour(node: Graph6Node<*>, direction: Direction) {
@ -74,32 +80,24 @@ abstract class AbstractStorageImportExport<T>(
}
}
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)
init {
exposeSideless(MatteryCapability.STORAGE_NODE, cell)
exposeAllSidesExcept(RelativeSide.FRONT, MatteryCapability.STORAGE_NODE, cell)
}
override fun invalidateCaps() {
super.invalidateCaps()
cell.invalidate()
target.invalidate()
valid = false
}
override fun reviveCaps() {
super.reviveCaps()
cell.revive()
target.revive()
valid = true
}
override fun setRemoved() {
super.setRemoved()
cell.destroy(level)
valid = false
}
override fun setLevel(p_155231_: Level) {
@ -127,14 +125,8 @@ abstract class AbstractStorageImportExport<T>(
abstract val filter: ItemFilter
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)
init {
savetable(::filter, FILTER_KEY)
}
companion object {
@ -146,9 +138,6 @@ abstract class AbstractStorageImportExport<T>(
class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState)
: AbstractStorageImportExport<IItemHandler>(MBlockEntities.STORAGE_IMPORTER, blockPos, blockState),
IItemHandler {
override val defaultDisplayName: Component
get() = MACHINE_NAME
override val filter = ItemFilter(MAX_FILTERS) { _, _, _ ->
setChangedLight()
}
@ -165,27 +154,8 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState)
override val targetCapability: Capability<IItemHandler>
get() = ForgeCapabilities.ITEM_HANDLER
private var valid = true
private var resolverItemHandler = LazyOptional.of<IItemHandler> { 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)
init {
front.Cap(ForgeCapabilities.ITEM_HANDLER, this)
}
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
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 {
return StoragePowerSupplierMenu(containerID, inventory, this)
}
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
private set
init {
savetable(::powerPassed, POWER_PASSED_KEY, Decimal::serializeNBT, Decimal.Companion::deserializeNBT)
}
override fun setLevel(p_155231_: Level) {
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() {
super.setRemoved()
cell.destroy(level)
valid = false
}
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 {
private val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_POWER_SUPPLIER}")
const val POWER_PASSED_KEY = "powerPassed"
}
}

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.block.entity.tech
import net.minecraft.core.BlockPos
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.MenuProvider
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.menu.tech.AndroidStationMenu
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.core.util.WriteOnce
@ -33,10 +31,7 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return AndroidStationMenu(containerID, inventory, this)
}
override val defaultDisplayName: Component
get() = MBlocks.ANDROID_STATION.name
override val energy = object : WorkerEnergyStorage(this@AndroidStationBlockEntity::setChangedLight,
val energy = object : WorkerEnergyStorage(this@AndroidStationBlockEntity::setChangedLight,
AndroidStationBlockEntity.Companion::CAPACITY,
AndroidStationBlockEntity.Companion::MAX_IO, { null }) {
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() {
if (!tickedOnve) {
tickedOnve = true
if (!tickedOnce) {
tickedOnce = true
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)

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.core.*
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.nbt.set
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")
}
override val droppableContainer: Container
get() = container
override val droppableContainer by ::container
private val itemHandler = container.handler(
object : MatteryContainerHooks {
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 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 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 {
return BatteryBankMenu(containerID, inventory, this)
}
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
resolverEnergyReceiver.invalidate()
resolverEnergyExtractor.invalidate()
resolverEnergy.invalidate()
resolverItemHandler.invalidate()
init {
exposeEnergySideless(energy)
exposeEnergy(RelativeSide.FRONT, energyExtractor)
if (isMekanismLoaded) {
mekanismResolverEnergyReceiver.invalidate()
mekanismResolverEnergyExtractor.invalidate()
mekanismResolverEnergy.invalidate()
for (side in RelativeSide.values()) {
if (side != RelativeSide.FRONT) {
exposeEnergy(side, energyReceiver)
}
}
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) {
@ -254,34 +215,6 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
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) {
override fun test(t: Direction): Boolean {
return blockState.facingOne == t
@ -317,8 +250,6 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
}
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.battery_bank")
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.capability.*
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.MatteryContainerHooks
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
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 {
return ChemicalGeneratorMenu(containerID, inventory, this)
}
private var valid = true
val container = MatteryContainer(this::setChangedLight, SLOTS)
override val droppableContainer: Container
get() = container
override val droppableContainer by ::container
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)
fun checkSurroundings() = consumers.update()
@ -61,16 +88,6 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe
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() {
super.invalidateCaps()
itemHandler.invalidate()
@ -108,25 +125,6 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe
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) {
super.setBlockState(p_155251_)
@ -212,7 +210,6 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe
private val THROUGHPUT get() = _THROUGHPUT.get()
private val GENERATION_SPEED get() = _GENERATION_SPEED.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 _GENERATION_SPEED: DecimalConfigValue by WriteOnce()

View File

@ -21,16 +21,16 @@ class CobblerBlockEntity(blockPos: BlockPos, blockState: BlockState)
return CobblerMenu(containerID, inventory, this)
}
override val energy = null
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 {
return false
}
}))
})
init {
exposeItemsGlobally(handler)
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)
}
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)
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
}
private var resolverEnergy = LazyOptional.of { energy }
private var valid = true
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
resolverEnergy.invalidate()
itemHandler.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
resolverEnergy = LazyOptional.of { energy }
itemHandler.revive()
init {
exposeEnergyGlobally(energy)
exposeItemsGlobally(itemHandler)
savetable(::container, INVENTORY_KEY)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
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() {
if (redstoneControl.isBlockedByRedstone)
return

View File

@ -38,7 +38,7 @@ class PlatePressBlockEntity(
p_155230_: BlockState
) : MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ::ItemJob), IDroppableContainer {
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
@ -51,8 +51,7 @@ class PlatePressBlockEntity(
}
}
override val droppableContainer: Container
get() = container
override val droppableContainer by ::container
val itemHandler = container.handler(object : MatteryContainerHooks {
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
return slot != SLOT_OUTPUT
@ -63,38 +62,12 @@ class PlatePressBlockEntity(
}
})
override fun invalidateCaps() {
super.invalidateCaps()
itemHandler.invalidate()
init {
savetable(::energy, ENERGY_KEY)
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 {
return PlatePressMenu(containerID, inventory, this)
}
@ -122,7 +95,6 @@ class PlatePressBlockEntity(
companion object {
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_OUTPUT = 1
}

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.block.matter
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.world.Containers
import net.minecraft.world.item.context.BlockPlaceContext
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.getShapeForEachState
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.math.facingOne
import ru.dbotthepony.mc.otm.shapes.BlockShapes
class PatternStorageBlock : RotatableMatteryBlock(), EntityBlock {
@ -51,7 +49,7 @@ class PatternStorageBlock : RotatableMatteryBlock(), EntityBlock {
val blockentity = level.getBlockEntity(blockPos)
if (blockentity is PatternStorageBlockEntity) {
Containers.dropContents(level, blockPos, blockentity.patternContainer)
Containers.dropContents(level, blockPos, blockentity.container)
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 mattery = getCapability(MatteryCapability.ENERGY)

View File

@ -30,7 +30,7 @@ sealed class BlockEnergyStorageImpl(
private val maxBatteryLevelProvider: () -> Decimal,
private val maxInputProvider: () -> Decimal?,
private val maxOutputProvider: () -> Decimal?,
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag>, IEnergyStorageImpl {
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag?>, IEnergyStorageImpl {
constructor(
listener: () -> Unit,
direction: FlowDirection,
@ -139,7 +139,8 @@ sealed class BlockEnergyStorageImpl(
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
maxBatteryLevelStorage = nbt.mapIf(ENERGY_STORED_MAX_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 maxReceiveSupplier: () -> Decimal? = { null },
protected val maxExtractSupplier: () -> Decimal? = maxReceiveSupplier
) : IMatterStorage, INBTSerializable<CompoundTag> {
) : IMatterStorage, INBTSerializable<CompoundTag?> {
constructor(
listener: Runnable?,
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"])
//maxStoredMatter = ImpreciseFraction.deserializeNBT(tag["max_storage"])
//maxReceive = if (tag.contains("max_receive")) ImpreciseFraction.deserializeNBT(tag["max_receive"]) else null

View File

@ -101,7 +101,7 @@ fun interface ItemFilterFullCallback {
class ItemFilter(
val size: Int,
private val modified: ItemFilterFullCallback? = null
) : INBTSerializable<CompoundTag> {
) : INBTSerializable<CompoundTag?> {
constructor(size: Int, modified: ItemFilterCallback?) :
this(size,
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
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 net.minecraft.world.SimpleContainer
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
abstract class MatteryPoweredMenu protected constructor(
@ -14,16 +15,14 @@ abstract class MatteryPoweredMenu protected constructor(
inventory: Inventory,
tile: MatteryPoweredBlockEntity? = null
) : MatteryMenu(menuType, containerID, inventory, tile) {
val powerWidget: LevelGaugeWidget
val powerWidget = LevelGaugeWidget(this, tile?.matteryEnergy)
val batterySlot: BatterySlot
val redstone = EnumInputWithFeedback(this, RedstoneSetting::class.java)
init {
if (tile == null) {
powerWidget = LevelGaugeWidget(this)
batterySlot = BatterySlot(SimpleContainer(1), 0)
} else {
powerWidget = LevelGaugeWidget(this, tile.energy)
batterySlot = BatterySlot(tile.batteryContainer, 0)
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) {
PatternSlot(patterns, it)