parent
ea6a237de8
commit
bd2132c06a
@ -18,7 +18,6 @@ import net.minecraftforge.common.capabilities.Capability
|
|||||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||||
import net.minecraftforge.common.util.LazyOptional
|
import net.minecraftforge.common.util.LazyOptional
|
||||||
import net.minecraftforge.energy.IEnergyStorage
|
import net.minecraftforge.energy.IEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.*
|
|
||||||
import ru.dbotthepony.mc.otm.block.IDroppableContainer
|
import ru.dbotthepony.mc.otm.block.IDroppableContainer
|
||||||
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
|
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
|
||||||
import ru.dbotthepony.mc.otm.capability.*
|
import ru.dbotthepony.mc.otm.capability.*
|
||||||
@ -33,11 +32,9 @@ import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
|||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
|
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
|
||||||
import ru.dbotthepony.mc.otm.core.math.defineDecimal
|
import ru.dbotthepony.mc.otm.core.math.defineDecimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.plus
|
|
||||||
import ru.dbotthepony.mc.otm.core.math.unaryMinus
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import java.lang.ref.WeakReference
|
import ru.dbotthepony.mc.otm.core.util.BESubscribeList
|
||||||
|
|
||||||
class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBlockEntity(MBlockEntities.CHEMICAL_GENERATOR, pos, state), IDroppableContainer {
|
class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBlockEntity(MBlockEntities.CHEMICAL_GENERATOR, pos, state), IDroppableContainer {
|
||||||
override val defaultDisplayName: Component
|
override val defaultDisplayName: Component
|
||||||
@ -53,11 +50,13 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
|
|||||||
get() = container
|
get() = container
|
||||||
val energy = GeneratorEnergyStorage(this::setChangedLight, CAPACITY, THROUGHPUT)
|
val energy = GeneratorEnergyStorage(this::setChangedLight, CAPACITY, THROUGHPUT)
|
||||||
|
|
||||||
private val consumers = ArrayList<LazyOptional<out IEnergyStorage>>()
|
private val consumers = BESubscribeList(this, ForgeCapabilities.ENERGY)
|
||||||
|
|
||||||
|
fun checkSurroundings() = consumers.update()
|
||||||
|
|
||||||
override fun setChangedLight() {
|
override fun setChangedLight() {
|
||||||
super.setChangedLight()
|
super.setChangedLight()
|
||||||
check = true
|
checkFuelSlot = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||||
@ -86,7 +85,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
|
|||||||
|
|
||||||
override fun setLevel(p_155231_: Level) {
|
override fun setLevel(p_155231_: Level) {
|
||||||
super.setLevel(p_155231_)
|
super.setLevel(p_155231_)
|
||||||
tickOnceServer(this::checkSurroundings)
|
tickOnceServer(consumers::update)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveAdditional(nbt: CompoundTag) {
|
override fun saveAdditional(nbt: CompoundTag) {
|
||||||
@ -107,36 +106,6 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
|
|||||||
workTicksTotal = nbt.getInt(WORK_TICKS_TOTAL_KEY)
|
workTicksTotal = nbt.getInt(WORK_TICKS_TOTAL_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkSurroundings() {
|
|
||||||
if (!valid)
|
|
||||||
return
|
|
||||||
|
|
||||||
val known = consumers.clone() as ArrayList<*>
|
|
||||||
consumers.clear()
|
|
||||||
val level = level ?: return
|
|
||||||
|
|
||||||
for (direction in Direction.values()) {
|
|
||||||
// нельзя выталкивать энергию через перед
|
|
||||||
if (direction == blockState.getValue(RotatableMatteryBlock.FACING))
|
|
||||||
continue
|
|
||||||
|
|
||||||
val resolver = level.getBlockEntity(blockPos + direction)?.getEnergySided(-direction)
|
|
||||||
|
|
||||||
resolver?.ifPresentK {
|
|
||||||
if (!known.contains(resolver)) {
|
|
||||||
val ref = WeakReference(this)
|
|
||||||
|
|
||||||
resolver.addListener {
|
|
||||||
if (SERVER_IS_LIVE)
|
|
||||||
ref.get()?.checkSurroundings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
consumers.add(resolver)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
||||||
if (slot == SLOT_INPUT)
|
if (slot == SLOT_INPUT)
|
||||||
@ -160,7 +129,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
|
|||||||
super.setBlockState(p_155251_)
|
super.setBlockState(p_155251_)
|
||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
tickOnceServer(this::checkSurroundings)
|
tickOnceServer(consumers::update)
|
||||||
}
|
}
|
||||||
|
|
||||||
var workTicks = 0
|
var workTicks = 0
|
||||||
@ -169,7 +138,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
|
|||||||
var workTicksTotal = 0
|
var workTicksTotal = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private var check = true
|
private var checkFuelSlot = true
|
||||||
|
|
||||||
private fun workWithPower(it: IEnergyStorage) {
|
private fun workWithPower(it: IEnergyStorage) {
|
||||||
val extracted = energy.extractEnergy(THROUGHPUT, true)
|
val extracted = energy.extractEnergy(THROUGHPUT, true)
|
||||||
@ -187,7 +156,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
|
|||||||
|
|
||||||
if (workTicks == 0) {
|
if (workTicks == 0) {
|
||||||
workTicksTotal = 0
|
workTicksTotal = 0
|
||||||
check = true
|
checkFuelSlot = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) {
|
if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) {
|
||||||
@ -197,7 +166,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
|
|||||||
level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
|
level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workTicks == 0 && !isBlockedByRedstone && check) {
|
if (workTicks == 0 && !isBlockedByRedstone && checkFuelSlot) {
|
||||||
if (!container[SLOT_INPUT].isEmpty) {
|
if (!container[SLOT_INPUT].isEmpty) {
|
||||||
val ticks = ForgeHooks.getBurnTime(container[SLOT_INPUT], null)
|
val ticks = ForgeHooks.getBurnTime(container[SLOT_INPUT], null)
|
||||||
val residue = container[SLOT_INPUT].item.getCraftingRemainingItem(container[SLOT_INPUT].copy().also { it.count = 1 })
|
val residue = container[SLOT_INPUT].item.getCraftingRemainingItem(container[SLOT_INPUT].copy().also { it.count = 1 })
|
||||||
@ -220,7 +189,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check = false
|
checkFuelSlot = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (energy.batteryLevel.isZero) return
|
if (energy.batteryLevel.isZero) return
|
||||||
@ -233,7 +202,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (consumer in consumers) {
|
for (consumer in consumers) {
|
||||||
consumer.ifPresent(this::workWithPower)
|
workWithPower(consumer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.core.collect
|
||||||
|
|
||||||
|
import java.util.WeakHashMap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around [WeakHashMap] to behave like set
|
||||||
|
*/
|
||||||
|
class WeakHashSet<E : Any> : MutableSet<E> {
|
||||||
|
private val backing = WeakHashMap<E, Unit>()
|
||||||
|
|
||||||
|
override fun add(element: E): Boolean {
|
||||||
|
return backing.put(element, Unit) == null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addAll(elements: Collection<E>): Boolean {
|
||||||
|
return elements.count(::add) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
backing.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun iterator(): MutableIterator<E> {
|
||||||
|
return backing.keys.iterator()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun remove(element: E): Boolean {
|
||||||
|
return backing.remove(element) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeAll(elements: Collection<E>): Boolean {
|
||||||
|
return backing.keys.removeAll(elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun retainAll(elements: Collection<E>): Boolean {
|
||||||
|
return backing.keys.retainAll(elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val size: Int
|
||||||
|
get() = backing.size
|
||||||
|
|
||||||
|
override fun contains(element: E): Boolean {
|
||||||
|
return backing.get(element) === Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun containsAll(elements: Collection<E>): Boolean {
|
||||||
|
return elements.all(::contains)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean {
|
||||||
|
return backing.isEmpty()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,130 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.core.util
|
||||||
|
|
||||||
|
import net.minecraft.core.Direction
|
||||||
|
import net.minecraft.core.SectionPos
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity
|
||||||
|
import net.minecraftforge.common.capabilities.Capability
|
||||||
|
import net.minecraftforge.common.util.LazyOptional
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.plus
|
||||||
|
import ru.dbotthepony.mc.otm.core.orNull
|
||||||
|
import ru.dbotthepony.mc.otm.onceServer
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
import java.util.EnumMap
|
||||||
|
import java.util.function.Predicate
|
||||||
|
|
||||||
|
open class BESubscribeList<T>(
|
||||||
|
val block: BlockEntity,
|
||||||
|
val capability: Capability<T>,
|
||||||
|
) : Predicate<Direction>, Iterable<T> {
|
||||||
|
private val knownCaps = WeakHashSet<LazyOptional<T>>()
|
||||||
|
private val trackedCaps = EnumMap<Direction, WeakReference<LazyOptional<T>>>(Direction::class.java)
|
||||||
|
|
||||||
|
var valid = true
|
||||||
|
set(value) {
|
||||||
|
if (value != field) {
|
||||||
|
field = value
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun invalidate() {
|
||||||
|
valid = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun revive() {
|
||||||
|
valid = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// override
|
||||||
|
protected open fun subscribe(direction: Direction, capability: LazyOptional<T>) {}
|
||||||
|
// override
|
||||||
|
protected open fun unsubscribe(direction: Direction, capability: LazyOptional<T>?) {}
|
||||||
|
|
||||||
|
override fun test(t: Direction): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun validate() {
|
||||||
|
val iterator = trackedCaps.iterator()
|
||||||
|
|
||||||
|
for ((k, v) in iterator) {
|
||||||
|
if (v.get() == null) {
|
||||||
|
unsubscribe(k, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun iterator(): Iterator<T> {
|
||||||
|
return object : Iterator<T> {
|
||||||
|
val iterator = trackedCaps.iterator()
|
||||||
|
var value: T? = null
|
||||||
|
|
||||||
|
private fun find() {
|
||||||
|
while (iterator.hasNext() && value == null) {
|
||||||
|
val (k, v) = iterator.next()
|
||||||
|
value = v.get()?.orNull()
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
iterator.remove()
|
||||||
|
unsubscribe(k, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
find()
|
||||||
|
return value != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun next(): T {
|
||||||
|
find()
|
||||||
|
val value = value
|
||||||
|
this.value = null
|
||||||
|
return value ?: throw NoSuchElementException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update() {
|
||||||
|
if (!valid)
|
||||||
|
return
|
||||||
|
|
||||||
|
val sorse = block.level?.chunkSource ?: return
|
||||||
|
var waitChunkLoad = false
|
||||||
|
|
||||||
|
for (it in Direction.stream().filter(this)) {
|
||||||
|
val pos = block.blockPos + it
|
||||||
|
val getChunk = sorse.getChunkNow(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z))
|
||||||
|
|
||||||
|
if (getChunk == null) {
|
||||||
|
waitChunkLoad = true
|
||||||
|
} else {
|
||||||
|
val cap = getChunk.getBlockEntity(pos)?.getCapability(capability)
|
||||||
|
val knownCap = trackedCaps[it]?.get()
|
||||||
|
|
||||||
|
if (cap != null && cap.isPresent) {
|
||||||
|
if (knownCap !== cap) {
|
||||||
|
if (knownCaps.add(cap)) {
|
||||||
|
val ref = WeakReference(this)
|
||||||
|
cap.addListener { ref.get()?.update() }
|
||||||
|
}
|
||||||
|
|
||||||
|
trackedCaps[it] = WeakReference(cap)
|
||||||
|
subscribe(it, cap)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trackedCaps.remove(it)
|
||||||
|
unsubscribe(it, knownCap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitChunkLoad) {
|
||||||
|
onceServer(::update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user