PhysicalConnectivity/src/main/kotlin/net/shadowfacts/phycon/block/redstone_emitter/RedstoneEmitterBlockEntity.kt

136 lines
3.7 KiB
Kotlin

package net.shadowfacts.phycon.block.redstone_emitter
import alexiil.mc.lib.attributes.item.GroupedItemInvView
import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound
import net.minecraft.text.TranslatableText
import net.minecraft.util.math.BlockPos
import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.api.util.IPAddress
import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.block.FaceDeviceBlock
import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.packet.DeviceRemovedPacket
import net.shadowfacts.phycon.packet.ReadInventoryPacket
import net.shadowfacts.phycon.packet.RequestInventoryPacket
import net.shadowfacts.phycon.util.ClientConfigurableDevice
import net.shadowfacts.phycon.util.GhostInv
import kotlin.math.round
/**
* @author shadowfacts
*/
class RedstoneEmitterBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.REDSTONE_EMITTER, pos, state),
ClientConfigurableDevice,
GhostInv {
private val inventoryCache = mutableMapOf<IPAddress, GroupedItemInvView>()
var cachedEmittedPower: Int = 0
private set
var stackToMonitor: ItemStack = ItemStack.EMPTY
override var ghostSlotStack: ItemStack
get() = stackToMonitor
set(value) { stackToMonitor = value }
var maxAmount = 64
var mode = Mode.ANALOG
set(value) {
field = value
recalculateRedstone()
}
override fun handle(packet: Packet) {
when (packet) {
is ReadInventoryPacket -> handleReadInventory(packet)
is DeviceRemovedPacket -> handleDeviceRemoved(packet)
}
}
private fun handleReadInventory(packet: ReadInventoryPacket) {
inventoryCache[packet.source] = packet.inventory
recalculateRedstone()
}
private fun handleDeviceRemoved(packet: DeviceRemovedPacket) {
inventoryCache.remove(packet.source)
recalculateRedstone()
}
override fun tick() {
super.tick()
if (!world!!.isClient && counter % 20 == 0L) {
if (counter % 80 == 0L) {
updateInventories()
} else if (counter % 20 == 0L) {
recalculateRedstone()
}
}
}
private fun updateInventories() {
sendPacket(RequestInventoryPacket(ipAddress))
}
private fun recalculateRedstone() {
if (world == null || world!!.isClient) return
if (stackToMonitor.isEmpty) {
cachedEmittedPower = 0
updateWorld()
return
}
val networkAmount = inventoryCache.values.fold(0) { acc, inv ->
acc + inv.getAmount(stackToMonitor)
}
cachedEmittedPower =
when (mode) {
Mode.ANALOG -> if (networkAmount == 0) {
0
} else {
1 + round(networkAmount / maxAmount.toDouble() * 14).toInt()
}
Mode.DIGITAL -> if (networkAmount >= maxAmount) 15 else 0
}
updateWorld()
}
private fun updateWorld() {
world!!.updateNeighborsAlways(pos, cachedState.block)
world!!.updateNeighborsAlways(pos.offset(cachedState[FaceDeviceBlock.FACING]), cachedState.block)
}
override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag)
tag.putInt("CachedEmittedPower", cachedEmittedPower)
tag.put("StackToMonitor", stackToMonitor.writeNbt(NbtCompound()))
writeDeviceConfiguration(tag)
}
override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag)
cachedEmittedPower = tag.getInt("CachedEmittedPower")
stackToMonitor = ItemStack.fromNbt(tag.getCompound("StackToMonitor"))
loadDeviceConfiguration(tag)
}
override fun writeDeviceConfiguration(tag: NbtCompound) {
tag.putInt("MaxAmount", maxAmount)
tag.putString("Mode", mode.name)
}
override fun loadDeviceConfiguration(tag: NbtCompound) {
maxAmount = tag.getInt("MaxAmount")
mode = Mode.valueOf(tag.getString("Mode"))
}
enum class Mode {
ANALOG, DIGITAL;
val friendlyName = TranslatableText("gui.phycon.redstone_emitter_mode.${name.lowercase()}")
}
}