Revisit quantum battery code and clean it up
This commit is contained in:
parent
8e2c1f25dc
commit
8e03b4363d
@ -17,18 +17,37 @@ import net.minecraftforge.fml.loading.FMLLoader
|
|||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage
|
import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage
|
||||||
import ru.dbotthepony.mc.otm.client.minecraft
|
import ru.dbotthepony.mc.otm.client.minecraft
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.AtomicallyInvalidatedLazy
|
||||||
import ru.dbotthepony.mc.otm.core.util.IConditionalTickable
|
import ru.dbotthepony.mc.otm.core.util.IConditionalTickable
|
||||||
import ru.dbotthepony.mc.otm.core.util.ITickable
|
import ru.dbotthepony.mc.otm.core.util.ITickable
|
||||||
import ru.dbotthepony.mc.otm.core.util.TickList
|
import ru.dbotthepony.mc.otm.core.util.TickList
|
||||||
import ru.dbotthepony.mc.otm.graph.GraphNodeList
|
import ru.dbotthepony.mc.otm.graph.GraphNodeList
|
||||||
import ru.dbotthepony.mc.otm.network.MatteryNetworkChannel
|
import ru.dbotthepony.mc.otm.network.MatteryNetworkChannel
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
private val preServerTick = TickList()
|
private val preServerTick = TickList()
|
||||||
private val postServerTick = TickList()
|
private val postServerTick = TickList()
|
||||||
private val preWorldTick = WeakHashMap<Level, TickList>()
|
private val preWorldTick = WeakHashMap<Level, TickList>()
|
||||||
private val postWorldTick = WeakHashMap<Level, TickList>()
|
private val postWorldTick = WeakHashMap<Level, TickList>()
|
||||||
|
|
||||||
|
private val clientThreads = WeakHashSet<Thread>()
|
||||||
|
private val serverThreads = WeakHashSet<Thread>()
|
||||||
|
|
||||||
|
private val serverCounter = AtomicInteger()
|
||||||
|
private var _server: MinecraftServer? = null
|
||||||
|
val isClient: Boolean by lazy { FMLLoader.getDist() == Dist.CLIENT }
|
||||||
|
|
||||||
|
fun <V> lazyPerServer(fn: (MinecraftServer) -> V): Lazy<V> {
|
||||||
|
return AtomicallyInvalidatedLazy(serverCounter) {
|
||||||
|
if (!SERVER_IS_LIVE)
|
||||||
|
throw IllegalStateException("No server is running")
|
||||||
|
|
||||||
|
fn.invoke(_server!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun onceServerPre(inTicks: Int, callback: Runnable): TickList.Timer? {
|
fun onceServerPre(inTicks: Int, callback: Runnable): TickList.Timer? {
|
||||||
if (!SERVER_IS_LIVE) {
|
if (!SERVER_IS_LIVE) {
|
||||||
LOGGER.error("Refusing to add timer $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
|
LOGGER.error("Refusing to add timer $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
|
||||||
@ -47,12 +66,6 @@ fun onceServer(inTicks: Int, callback: Runnable): TickList.Timer? {
|
|||||||
return postServerTick.Timer(inTicks, callback)
|
return postServerTick.Timer(inTicks, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var _server: MinecraftServer? = null
|
|
||||||
private var _serverThread: Thread? = null
|
|
||||||
private var _clientThread: Thread? = null
|
|
||||||
|
|
||||||
val isClient: Boolean by lazy { FMLLoader.getDist() == Dist.CLIENT }
|
|
||||||
|
|
||||||
private val isPausedImpl: Boolean get() {
|
private val isPausedImpl: Boolean get() {
|
||||||
val server = _server
|
val server = _server
|
||||||
|
|
||||||
@ -64,7 +77,7 @@ private val isPausedImpl: Boolean get() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val isPaused: Boolean get() {
|
val isPaused: Boolean get() {
|
||||||
if (_clientThread === null) {
|
if (clientThreads.isEmpty()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,11 +85,7 @@ val isPaused: Boolean get() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun recordClientThread() {
|
fun recordClientThread() {
|
||||||
if (_clientThread != null) {
|
clientThreads.add(Thread.currentThread())
|
||||||
throw IllegalStateException("Already have client channel")
|
|
||||||
}
|
|
||||||
|
|
||||||
_clientThread = Thread.currentThread()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runIfClient(lambda: () -> Unit) {
|
fun runIfClient(lambda: () -> Unit) {
|
||||||
@ -119,11 +128,11 @@ fun <V> runOnClient(value: V, lambda: () -> V): V {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isServerThread(): Boolean {
|
fun isServerThread(): Boolean {
|
||||||
return Thread.currentThread() === _serverThread
|
return Thread.currentThread() in serverThreads
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isClientThread(): Boolean {
|
fun isClientThread(): Boolean {
|
||||||
return Thread.currentThread() === _clientThread
|
return Thread.currentThread() in clientThreads
|
||||||
}
|
}
|
||||||
|
|
||||||
val MINECRAFT_SERVER: MinecraftServer
|
val MINECRAFT_SERVER: MinecraftServer
|
||||||
@ -146,6 +155,7 @@ private val LOGGER = LogManager.getLogger()
|
|||||||
fun onServerTick(event: ServerTickEvent) {
|
fun onServerTick(event: ServerTickEvent) {
|
||||||
if (event.phase === TickEvent.Phase.START) {
|
if (event.phase === TickEvent.Phase.START) {
|
||||||
preServerTick.tick()
|
preServerTick.tick()
|
||||||
|
serverThreads.add(Thread.currentThread())
|
||||||
} else {
|
} else {
|
||||||
postServerTick.tick()
|
postServerTick.tick()
|
||||||
// чтоб не плодить кучу подписчиков, вызовем напрямую отсюда
|
// чтоб не плодить кучу подписчиков, вызовем напрямую отсюда
|
||||||
@ -158,6 +168,12 @@ fun onServerTick(event: ServerTickEvent) {
|
|||||||
fun onWorldTick(event: LevelTickEvent) {
|
fun onWorldTick(event: LevelTickEvent) {
|
||||||
if (event.phase === TickEvent.Phase.START) {
|
if (event.phase === TickEvent.Phase.START) {
|
||||||
preWorldTick[event.level]?.tick()
|
preWorldTick[event.level]?.tick()
|
||||||
|
|
||||||
|
if (event.side.isClient) {
|
||||||
|
clientThreads.add(Thread.currentThread())
|
||||||
|
} else if (event.side.isServer) {
|
||||||
|
serverThreads.add(Thread.currentThread())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
postWorldTick[event.level]?.tick()
|
postWorldTick[event.level]?.tick()
|
||||||
}
|
}
|
||||||
@ -254,13 +270,15 @@ fun onServerStarting(event: ServerAboutToStartEvent) {
|
|||||||
clear()
|
clear()
|
||||||
SERVER_IS_LIVE = true
|
SERVER_IS_LIVE = true
|
||||||
_server = event.server
|
_server = event.server
|
||||||
_serverThread = Thread.currentThread()
|
serverThreads.add(Thread.currentThread())
|
||||||
|
serverCounter.incrementAndGet()
|
||||||
MatteryNetworkChannel.onServerStarting()
|
MatteryNetworkChannel.onServerStarting()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onServerStopping(event: ServerStoppingEvent) {
|
fun onServerStopping(event: ServerStoppingEvent) {
|
||||||
clear()
|
clear()
|
||||||
SERVER_IS_LIVE = false
|
SERVER_IS_LIVE = false
|
||||||
|
serverCounter.incrementAndGet()
|
||||||
MatteryNetworkChannel.onServerStopping()
|
MatteryNetworkChannel.onServerStopping()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,6 +291,6 @@ fun onServerStopped(event: ServerStoppedEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_server = null
|
_server = null
|
||||||
_serverThread = null
|
serverCounter.incrementAndGet()
|
||||||
MatteryNetworkChannel.onServerStopped()
|
MatteryNetworkChannel.onServerStopped()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ru.dbotthepony.mc.otm.capability
|
package ru.dbotthepony.mc.otm.capability
|
||||||
|
|
||||||
import com.google.common.collect.Streams
|
import com.google.common.collect.Streams
|
||||||
|
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet
|
||||||
import net.minecraft.ChatFormatting
|
import net.minecraft.ChatFormatting
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
@ -30,6 +31,9 @@ import ru.dbotthepony.mc.otm.container.iterator
|
|||||||
import ru.dbotthepony.mc.otm.container.stream
|
import ru.dbotthepony.mc.otm.container.stream
|
||||||
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
|
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
|
||||||
import ru.dbotthepony.mc.otm.core.collect.ContainerItemStackEntry
|
import ru.dbotthepony.mc.otm.core.collect.ContainerItemStackEntry
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.concatIterators
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.map
|
||||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.orNull
|
import ru.dbotthepony.mc.otm.core.orNull
|
||||||
@ -219,25 +223,25 @@ fun ICapabilityProvider.getMatteryEnergySided(side: Direction? = null): LazyOpti
|
|||||||
*
|
*
|
||||||
* Contains all items that player might carry
|
* Contains all items that player might carry
|
||||||
*/
|
*/
|
||||||
fun Player.itemsStream(includeCosmetics: Boolean = true): Stream<out ItemStack> {
|
fun Player.items(includeCosmetics: Boolean = true): Iterator<ItemStack> {
|
||||||
val streams = ArrayList<Stream<out ItemStack>>()
|
val iterators = ArrayList<Iterator<ItemStack>>()
|
||||||
streams.add(inventory.stream())
|
iterators.add(inventory.iterator())
|
||||||
|
|
||||||
matteryPlayer?.let {
|
matteryPlayer?.let {
|
||||||
if (it.hasExopack) {
|
if (it.hasExopack) {
|
||||||
streams.add(it.exopackContainer.stream())
|
iterators.add(it.exopackContainer.iterator())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCuriosLoaded) {
|
if (isCuriosLoaded) {
|
||||||
streams.add(curiosStream(includeCosmetics))
|
iterators.add(curiosStream(includeCosmetics))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeCosmetics && isCosmeticArmorLoaded) {
|
if (includeCosmetics && isCosmeticArmorLoaded) {
|
||||||
streams.add(cosmeticArmorStream())
|
iterators.add(cosmeticArmorStream())
|
||||||
}
|
}
|
||||||
|
|
||||||
return streams.stream().flatMap { it }
|
return concatIterators(iterators)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -245,20 +249,20 @@ fun Player.itemsStream(includeCosmetics: Boolean = true): Stream<out ItemStack>
|
|||||||
*
|
*
|
||||||
* Contains all items that player might see/access ([itemsStream] + open container's items)
|
* Contains all items that player might see/access ([itemsStream] + open container's items)
|
||||||
*/
|
*/
|
||||||
fun Player.allItemsStream(includeCosmetics: Boolean = true): Stream<out ItemStack> {
|
fun Player.allItems(includeCosmetics: Boolean = true): Iterator<ItemStack> {
|
||||||
if (containerMenu == inventoryMenu || containerMenu == matteryPlayer?.exoPackMenu) {
|
if (containerMenu == inventoryMenu || containerMenu == matteryPlayer?.exoPackMenu) {
|
||||||
return itemsStream(includeCosmetics)
|
return items(includeCosmetics)
|
||||||
}
|
}
|
||||||
|
|
||||||
val seen = IdentityHashMap<ItemStack, Unit>(containerMenu.slots.size)
|
val seen = ReferenceOpenHashSet<ItemStack>(containerMenu.slots.size)
|
||||||
|
|
||||||
for (slot in containerMenu.slots) {
|
for (slot in containerMenu.slots) {
|
||||||
seen[slot.item] = Unit
|
seen.add(slot.item)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Streams.concat(
|
return concatIterators(
|
||||||
itemsStream(includeCosmetics).filter { it.isEmpty || it !in seen },
|
items(includeCosmetics).filter { it.isNotEmpty && it !in seen },
|
||||||
containerMenu.slots.stream().map { it.item })
|
containerMenu.slots.iterator().map { it.item })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,8 +24,10 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.RectangleButtonPanel
|
|||||||
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton.Companion.BUTTON_ACTIVE
|
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton.Companion.BUTTON_ACTIVE
|
||||||
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton.Companion.BUTTON_INACTIVE
|
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleButton.Companion.BUTTON_INACTIVE
|
||||||
import ru.dbotthepony.mc.otm.container.awareStream
|
import ru.dbotthepony.mc.otm.container.awareStream
|
||||||
|
import ru.dbotthepony.mc.otm.container.iterator
|
||||||
import ru.dbotthepony.mc.otm.container.stream
|
import ru.dbotthepony.mc.otm.container.stream
|
||||||
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
|
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.emptyIterator
|
||||||
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
|
|
||||||
@ -71,16 +73,16 @@ private class CosmeticSlot(container: Container, private val slot: EquipmentSlot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Player.cosmeticArmorStream(): Stream<out ItemStack> {
|
fun Player.cosmeticArmorStream(): Iterator<ItemStack> {
|
||||||
if (!isCosmeticArmorLoaded) {
|
if (!isCosmeticArmorLoaded) {
|
||||||
return Stream.empty()
|
return emptyIterator()
|
||||||
}
|
}
|
||||||
|
|
||||||
return cosmeticArmorStreamImpl()
|
return cosmeticArmorStreamImpl()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Player.cosmeticArmorStreamImpl(): Stream<out ItemStack> {
|
private fun Player.cosmeticArmorStreamImpl(): Iterator<ItemStack> {
|
||||||
val manager = ModObjects.invMan ?: return Stream.empty()
|
val manager = ModObjects.invMan ?: return emptyIterator()
|
||||||
|
|
||||||
val container = if (this !is ServerPlayer) {
|
val container = if (this !is ServerPlayer) {
|
||||||
manager.getCosArmorInventoryClient(uuid)
|
manager.getCosArmorInventoryClient(uuid)
|
||||||
@ -88,7 +90,7 @@ private fun Player.cosmeticArmorStreamImpl(): Stream<out ItemStack> {
|
|||||||
manager.getCosArmorInventory(uuid)
|
manager.getCosArmorInventory(uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (container as Container).stream()
|
return (container as Container).iterator()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Player.cosmeticArmorAwareStream(): Stream<out AwareItemStack> {
|
fun Player.cosmeticArmorAwareStream(): Stream<out AwareItemStack> {
|
||||||
|
@ -11,8 +11,11 @@ import net.minecraftforge.network.PacketDistributor
|
|||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||||
import ru.dbotthepony.mc.otm.container.awareStream
|
import ru.dbotthepony.mc.otm.container.awareStream
|
||||||
|
import ru.dbotthepony.mc.otm.container.iterator
|
||||||
import ru.dbotthepony.mc.otm.container.stream
|
import ru.dbotthepony.mc.otm.container.stream
|
||||||
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
|
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.concatIterators
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.emptyIterator
|
||||||
import ru.dbotthepony.mc.otm.core.orNull
|
import ru.dbotthepony.mc.otm.core.orNull
|
||||||
import ru.dbotthepony.mc.otm.menu.PlayerSlot
|
import ru.dbotthepony.mc.otm.menu.PlayerSlot
|
||||||
import top.theillusivec4.curios.api.CuriosApi
|
import top.theillusivec4.curios.api.CuriosApi
|
||||||
@ -85,27 +88,27 @@ val Player.curiosSlots: List<PlayerSlot<Slot, Slot>> get() {
|
|||||||
return getCuriosSlotsImpl()
|
return getCuriosSlotsImpl()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Player.curiosStreamImpl(includeCosmetics: Boolean): Stream<out ItemStack> {
|
private fun Player.curiosStreamImpl(includeCosmetics: Boolean): Iterator<ItemStack> {
|
||||||
val handler = getCapability(MatteryCapability.CURIOS_INVENTORY).orNull() ?: return Stream.empty()
|
val handler = getCapability(MatteryCapability.CURIOS_INVENTORY).orNull() ?: return emptyIterator()
|
||||||
|
|
||||||
val result = ArrayList<Stream<out ItemStack>>()
|
val result = ArrayList<Iterator<ItemStack>>()
|
||||||
|
|
||||||
for ((identifier, curio) in handler.curios) {
|
for ((identifier, curio) in handler.curios) {
|
||||||
result.add(curio.stacks.stream())
|
result.add(curio.stacks.iterator())
|
||||||
|
|
||||||
if (includeCosmetics && curio.hasCosmetic()) {
|
if (includeCosmetics && curio.hasCosmetic()) {
|
||||||
result.add(curio.cosmeticStacks.stream())
|
result.add(curio.cosmeticStacks.iterator())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.stream().flatMap { it }
|
return concatIterators(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Player.curiosStream(includeCosmetics: Boolean = true): Stream<out ItemStack> {
|
fun Player.curiosStream(includeCosmetics: Boolean = true): Iterator<ItemStack> {
|
||||||
return Stream.empty()
|
return emptyIterator()
|
||||||
|
|
||||||
if (!isCuriosLoaded) {
|
if (!isCuriosLoaded) {
|
||||||
return Stream.empty()
|
return emptyIterator()
|
||||||
}
|
}
|
||||||
|
|
||||||
return curiosStreamImpl(includeCosmetics)
|
return curiosStreamImpl(includeCosmetics)
|
||||||
|
@ -6,6 +6,8 @@ import net.minecraft.world.item.ItemStack
|
|||||||
import net.minecraftforge.items.IItemHandler
|
import net.minecraftforge.items.IItemHandler
|
||||||
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
|
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
|
||||||
import ru.dbotthepony.mc.otm.core.collect.ItemHandlerItemStackEntry
|
import ru.dbotthepony.mc.otm.core.collect.ItemHandlerItemStackEntry
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||||
|
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
import java.util.stream.StreamSupport
|
import java.util.stream.StreamSupport
|
||||||
@ -48,7 +50,7 @@ class ItemHandlerAwareSpliterator(private val handler: IItemHandler, offset: Int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IItemHandler.iterator(): Iterator<ItemStack> = Spliterators.iterator(spliterator())
|
fun IItemHandler.iterator(): Iterator<ItemStack> = Spliterators.iterator(spliterator()).filter { it.isNotEmpty }
|
||||||
fun IItemHandler.spliterator(): Spliterator<out ItemStack> = ItemHandlerSpliterator(this)
|
fun IItemHandler.spliterator(): Spliterator<out ItemStack> = ItemHandlerSpliterator(this)
|
||||||
fun IItemHandler.awareSpliterator(): Spliterator<out AwareItemStack> = ItemHandlerAwareSpliterator(this)
|
fun IItemHandler.awareSpliterator(): Spliterator<out AwareItemStack> = ItemHandlerAwareSpliterator(this)
|
||||||
fun IItemHandler.stream(): Stream<out ItemStack> = StreamSupport.stream(spliterator(), false)
|
fun IItemHandler.stream(): Stream<out ItemStack> = StreamSupport.stream(spliterator(), false)
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.core.collect
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.Hash
|
||||||
|
import java.lang.ref.Reference
|
||||||
|
|
||||||
|
object ReferenceHashStrategy : Hash.Strategy<Any?> {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun equals(a: Any?, b: Any?): Boolean {
|
||||||
|
if (a === b) return true
|
||||||
|
|
||||||
|
if (a is Reference<*>) {
|
||||||
|
if (a.refersTo(null) || b == null) return false
|
||||||
|
|
||||||
|
if (b is Reference<*>) {
|
||||||
|
if (b.refersTo(null)) return false
|
||||||
|
return (b as Reference<Any>).refersTo(a.get() ?: return false)
|
||||||
|
} else {
|
||||||
|
return (a as Reference<Any>).refersTo(b)
|
||||||
|
}
|
||||||
|
} else if (b is Reference<*>) {
|
||||||
|
if (b.refersTo(null) || a == null) return false
|
||||||
|
return (b as Reference<Any>).refersTo(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
return a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(o: Any?): Int {
|
||||||
|
return o.hashCode()
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import java.util.stream.Collector
|
|||||||
*/
|
*/
|
||||||
class FilteringIterator<T>(private val parent: Iterator<T>, private val predicate: Predicate<in T>) : MutableIterator<T> {
|
class FilteringIterator<T>(private val parent: Iterator<T>, private val predicate: Predicate<in T>) : MutableIterator<T> {
|
||||||
private var foundValue: Any? = Companion
|
private var foundValue: Any? = Companion
|
||||||
|
private var returned = false
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
if (foundValue === Companion) {
|
if (foundValue === Companion) {
|
||||||
@ -58,16 +59,14 @@ class FilteringIterator<T>(private val parent: Iterator<T>, private val predicat
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.foundValue = Companion
|
this.foundValue = Companion
|
||||||
|
returned = true
|
||||||
return foundValue as T
|
return foundValue as T
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun remove() {
|
override fun remove() {
|
||||||
if (foundValue === Companion) {
|
if (!returned) throw NoSuchElementException()
|
||||||
throw NoSuchElementException()
|
|
||||||
}
|
|
||||||
|
|
||||||
(parent as MutableIterator<T>).remove()
|
(parent as MutableIterator<T>).remove()
|
||||||
foundValue = Companion
|
returned = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object
|
private companion object
|
||||||
@ -197,6 +196,10 @@ fun <T> concatIterators(a: Iterator<T>): MutableIterator<T> {
|
|||||||
return a as MutableIterator<T>
|
return a as MutableIterator<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> concatIterators(iterators: Iterable<Iterator<T>>): MutableIterator<T> {
|
||||||
|
return iterators.iterator().flatMap { it }
|
||||||
|
}
|
||||||
|
|
||||||
fun <T> concatIterators(vararg iterators: Iterator<T>): MutableIterator<T> {
|
fun <T> concatIterators(vararg iterators: Iterator<T>): MutableIterator<T> {
|
||||||
return iterators.iterator().flatMap { it }
|
return iterators.iterator().flatMap { it }
|
||||||
}
|
}
|
||||||
@ -243,7 +246,7 @@ fun <T> Iterator<T>.reduce(identity: T, reducer: (T, T) -> T): T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <T> Iterator<T>.reduce(identity: T, reducer: BinaryOperator<T>): T = reduce(identity, reducer::apply)
|
fun <T> Iterator<T>.reduce(identity: T, reducer: BinaryOperator<T>): T = reduce(identity, reducer::apply)
|
||||||
fun <T> Iterator<T?>.filterNotNull(): Iterator<T> = filter { it != null } as Iterator<T>
|
fun <T> Iterator<T?>.filterNotNull(): MutableIterator<T> = filter { it != null } as MutableIterator<T>
|
||||||
|
|
||||||
fun <T> Iterator<T>.any(predicate: Predicate<in T>): Boolean {
|
fun <T> Iterator<T>.any(predicate: Predicate<in T>): Boolean {
|
||||||
for (value in this) {
|
for (value in this) {
|
||||||
@ -363,3 +366,7 @@ fun <T> Iterator<T>.maybe(): T? {
|
|||||||
else
|
else
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> emptyIterator(): MutableIterator<T> {
|
||||||
|
return ObjectIterators.emptyIterator()
|
||||||
|
}
|
||||||
|
@ -1,53 +1,76 @@
|
|||||||
package ru.dbotthepony.mc.otm.core.collect
|
package ru.dbotthepony.mc.otm.core.collect
|
||||||
|
|
||||||
import java.util.WeakHashMap
|
import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.HashedWeakReference
|
||||||
|
import java.lang.ref.ReferenceQueue
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper around [WeakHashMap] to behave like set
|
|
||||||
*/
|
|
||||||
class WeakHashSet<E : Any> : MutableSet<E> {
|
class WeakHashSet<E : Any> : MutableSet<E> {
|
||||||
private val backing = WeakHashMap<E, Unit>()
|
private val queue = ReferenceQueue<E>()
|
||||||
|
private val backing = ObjectOpenCustomHashSet<Any>(ReferenceHashStrategy)
|
||||||
|
|
||||||
|
private fun purge() {
|
||||||
|
var next = queue.poll()
|
||||||
|
|
||||||
|
while (next != null) {
|
||||||
|
backing.remove(next)
|
||||||
|
next = queue.poll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun add(element: E): Boolean {
|
override fun add(element: E): Boolean {
|
||||||
return backing.put(element, Unit) == null
|
purge()
|
||||||
|
if (element in backing) return false
|
||||||
|
return backing.add(HashedWeakReference(element, queue))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addAll(elements: Collection<E>): Boolean {
|
override fun addAll(elements: Collection<E>): Boolean {
|
||||||
return elements.count(::add) > 0
|
var any = false
|
||||||
|
elements.forEach { any = add(it) || any }
|
||||||
|
return any
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clear() {
|
override fun clear() {
|
||||||
backing.clear()
|
backing.clear()
|
||||||
|
while (queue.poll() != null) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun iterator(): MutableIterator<E> {
|
override fun iterator(): MutableIterator<E> {
|
||||||
return backing.keys.iterator()
|
purge()
|
||||||
|
return backing.iterator().map { (it as HashedWeakReference<E>).get() }.filterNotNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(element: E): Boolean {
|
override fun remove(element: E): Boolean {
|
||||||
return backing.remove(element) != null
|
purge()
|
||||||
|
return backing.remove(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeAll(elements: Collection<E>): Boolean {
|
override fun removeAll(elements: Collection<E>): Boolean {
|
||||||
return backing.keys.removeAll(elements)
|
purge()
|
||||||
|
return backing.removeAll(elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun retainAll(elements: Collection<E>): Boolean {
|
override fun retainAll(elements: Collection<E>): Boolean {
|
||||||
return backing.keys.retainAll(elements)
|
purge()
|
||||||
|
return backing.retainAll(elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val size: Int
|
override val size: Int get() {
|
||||||
get() = backing.size
|
purge()
|
||||||
|
return backing.size
|
||||||
|
}
|
||||||
|
|
||||||
override fun contains(element: E): Boolean {
|
override fun contains(element: E): Boolean {
|
||||||
return backing.get(element) === Unit
|
purge()
|
||||||
|
return backing.contains(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun containsAll(elements: Collection<E>): Boolean {
|
override fun containsAll(elements: Collection<E>): Boolean {
|
||||||
return elements.all(::contains)
|
purge()
|
||||||
|
return backing.containsAll(elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isEmpty(): Boolean {
|
override fun isEmpty(): Boolean {
|
||||||
|
purge()
|
||||||
return backing.isEmpty()
|
return backing.isEmpty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -665,7 +665,7 @@ class Decimal private constructor(val mag: BigInteger, marker: Nothing?) : Numbe
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun read(buff: FriendlyByteBuf): Decimal {
|
fun read(buff: FriendlyByteBuf): Decimal {
|
||||||
return Decimal(BigInteger(buff.readByteArray()))
|
return Decimal(BigInteger(buff.readByteArray()), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.core.util
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
|
||||||
|
class AtomicallyInvalidatedLazy<V>(private val invalidator: AtomicInteger, private val initializer: () -> V) : Lazy<V> {
|
||||||
|
@Volatile
|
||||||
|
private var thisCounter = -1
|
||||||
|
@Volatile
|
||||||
|
private var stored: Any? = Companion
|
||||||
|
private val lock = ReentrantLock()
|
||||||
|
|
||||||
|
override val value: V get() {
|
||||||
|
if (thisCounter != invalidator.get()) {
|
||||||
|
lock.lock()
|
||||||
|
this.stored = Companion
|
||||||
|
thisCounter = invalidator.get()
|
||||||
|
lock.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
var stored = stored
|
||||||
|
|
||||||
|
if (stored !== Companion)
|
||||||
|
return stored as V
|
||||||
|
|
||||||
|
lock.lock()
|
||||||
|
|
||||||
|
try {
|
||||||
|
stored = initializer.invoke()
|
||||||
|
this.stored = stored
|
||||||
|
return stored
|
||||||
|
} finally {
|
||||||
|
lock.unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isInitialized(): Boolean {
|
||||||
|
return stored !== Companion && thisCounter == invalidator.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.core.util
|
||||||
|
|
||||||
|
import java.lang.ref.ReferenceQueue
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [WeakReference], but with [hashCode] overridden with hash of referent object
|
||||||
|
*/
|
||||||
|
@Suppress("EqualsOrHashCode")
|
||||||
|
class HashedWeakReference<T : Any> : WeakReference<T> {
|
||||||
|
constructor(value: T) : super(value) {
|
||||||
|
hash = value.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(value: T, queue: ReferenceQueue<T>) : super(value, queue) {
|
||||||
|
hash = value.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val hash: Int
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "HashedWeakReference[hash=$hash]"
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,8 @@ import net.minecraft.world.level.storage.loot.LootContext
|
|||||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
||||||
import ru.dbotthepony.mc.otm.capability.itemsStream
|
import ru.dbotthepony.mc.otm.capability.items
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||||
import ru.dbotthepony.mc.otm.data.Codec2Serializer
|
import ru.dbotthepony.mc.otm.data.Codec2Serializer
|
||||||
import ru.dbotthepony.mc.otm.data.get
|
import ru.dbotthepony.mc.otm.data.get
|
||||||
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
||||||
@ -19,7 +20,7 @@ data class ItemInInventoryCondition(
|
|||||||
val matchCosmetics: Boolean = true,
|
val matchCosmetics: Boolean = true,
|
||||||
) : LootItemCondition, LootItemCondition.Builder {
|
) : LootItemCondition, LootItemCondition.Builder {
|
||||||
override fun test(t: LootContext): Boolean {
|
override fun test(t: LootContext): Boolean {
|
||||||
val matches = t[LootContextParams.LAST_DAMAGE_PLAYER]?.itemsStream(matchCosmetics)?.filter {
|
val matches = t[LootContextParams.LAST_DAMAGE_PLAYER]?.items(matchCosmetics)?.filter {
|
||||||
if (it.isEmpty) {
|
if (it.isEmpty) {
|
||||||
return@filter false
|
return@filter false
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
package ru.dbotthepony.mc.otm.item
|
package ru.dbotthepony.mc.otm.item
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
|
|
||||||
import net.minecraft.ChatFormatting
|
import net.minecraft.ChatFormatting
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.nbt.ByteArrayTag
|
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.Tag
|
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.world.item.*
|
import net.minecraft.world.item.Item
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.minecraft.world.item.Rarity
|
||||||
|
import net.minecraft.world.item.TooltipFlag
|
||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
|
import net.minecraft.world.level.saveddata.SavedData
|
||||||
import net.minecraftforge.client.event.ClientPlayerNetworkEvent
|
import net.minecraftforge.client.event.ClientPlayerNetworkEvent
|
||||||
import net.minecraftforge.common.capabilities.Capability
|
import net.minecraftforge.common.capabilities.Capability
|
||||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||||
@ -21,63 +22,140 @@ import net.minecraftforge.event.TickEvent
|
|||||||
import net.minecraftforge.event.TickEvent.ServerTickEvent
|
import net.minecraftforge.event.TickEvent.ServerTickEvent
|
||||||
import net.minecraftforge.network.NetworkEvent
|
import net.minecraftforge.network.NetworkEvent
|
||||||
import net.minecraftforge.registries.ForgeRegistries
|
import net.minecraftforge.registries.ForgeRegistries
|
||||||
import net.minecraftforge.registries.ForgeRegistry
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
import ru.dbotthepony.mc.otm.*
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.*
|
import ru.dbotthepony.mc.otm.capability.allItems
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.getBarColor
|
import ru.dbotthepony.mc.otm.capability.energy.getBarColor
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.getBarWidth
|
import ru.dbotthepony.mc.otm.capability.energy.getBarWidth
|
||||||
|
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
|
||||||
|
import ru.dbotthepony.mc.otm.capability.matteryEnergy
|
||||||
import ru.dbotthepony.mc.otm.compat.mekanism.Mattery2MekanismEnergyWrapper
|
import ru.dbotthepony.mc.otm.compat.mekanism.Mattery2MekanismEnergyWrapper
|
||||||
import ru.dbotthepony.mc.otm.config.EnergyBalanceValues
|
import ru.dbotthepony.mc.otm.config.EnergyBalanceValues
|
||||||
import ru.dbotthepony.mc.otm.core.*
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
|
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||||
|
import ru.dbotthepony.mc.otm.core.getID
|
||||||
|
import ru.dbotthepony.mc.otm.core.getValue
|
||||||
|
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.getDecimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.readDecimal
|
import ru.dbotthepony.mc.otm.core.math.readDecimal
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.set
|
||||||
import ru.dbotthepony.mc.otm.core.math.writeDecimal
|
import ru.dbotthepony.mc.otm.core.math.writeDecimal
|
||||||
|
import ru.dbotthepony.mc.otm.core.nbt.getUUIDSafe
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
|
import ru.dbotthepony.mc.otm.core.orThrow
|
||||||
|
import ru.dbotthepony.mc.otm.core.tagNotNull
|
||||||
import ru.dbotthepony.mc.otm.core.util.formatPower
|
import ru.dbotthepony.mc.otm.core.util.formatPower
|
||||||
|
import ru.dbotthepony.mc.otm.isClientThread
|
||||||
|
import ru.dbotthepony.mc.otm.isServerThread
|
||||||
|
import ru.dbotthepony.mc.otm.lazyPerServer
|
||||||
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
|
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
|
||||||
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
||||||
import ru.dbotthepony.mc.otm.network.packetHandled
|
import ru.dbotthepony.mc.otm.network.packetHandled
|
||||||
import ru.dbotthepony.mc.otm.saveddata.SavedCountingMap
|
import java.util.*
|
||||||
|
import java.util.function.Function
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
import kotlin.collections.MutableList
|
||||||
|
import kotlin.collections.component1
|
||||||
|
import kotlin.collections.component2
|
||||||
|
import kotlin.collections.forEach
|
||||||
|
import kotlin.collections.iterator
|
||||||
|
import kotlin.collections.set
|
||||||
|
|
||||||
class QuantumBatteryItem : Item {
|
class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanceValues?) : Item(Properties().stacksTo(1).rarity(if (balanceValues == null) Rarity.EPIC else Rarity.UNCOMMON)) {
|
||||||
class Data(
|
val isCreative = balanceValues == null
|
||||||
val parent: SavedCountingMap<Data>?,
|
|
||||||
val index: Int = -1,
|
|
||||||
energy: Decimal = Decimal.ZERO,
|
|
||||||
passed: Decimal = Decimal.ZERO,
|
|
||||||
received: Decimal = Decimal.ZERO,
|
|
||||||
) {
|
|
||||||
constructor(
|
|
||||||
energy: Decimal = Decimal.ZERO,
|
|
||||||
passed: Decimal = Decimal.ZERO,
|
|
||||||
received: Decimal = Decimal.ZERO,
|
|
||||||
) : this(null, -1, energy, passed, received)
|
|
||||||
|
|
||||||
var energy: Decimal = energy
|
interface IValues {
|
||||||
set(value) {
|
val uuid: UUID
|
||||||
if (field != value) {
|
var energy: Decimal
|
||||||
|
var passed: Decimal
|
||||||
|
var received: Decimal
|
||||||
|
val isServer: Boolean
|
||||||
|
|
||||||
|
fun serialize(): CompoundTag {
|
||||||
|
return CompoundTag().also {
|
||||||
|
it["energy"] = energy
|
||||||
|
it["passed"] = passed
|
||||||
|
it["received"] = received
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deserialize(nbt: CompoundTag) {
|
||||||
|
energy = nbt.getDecimal("energy")
|
||||||
|
passed = nbt.getDecimal("passed")
|
||||||
|
received = nbt.getDecimal("received")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnboundValues(override val uuid: UUID = UUID.randomUUID()) : IValues {
|
||||||
|
override var energy: Decimal = Decimal.ZERO
|
||||||
|
override var passed: Decimal = Decimal.ZERO
|
||||||
|
override var received: Decimal = Decimal.ZERO
|
||||||
|
override val isServer: Boolean
|
||||||
|
get() = false
|
||||||
|
}
|
||||||
|
|
||||||
|
class Data() : SavedData() {
|
||||||
|
constructor(nbt: CompoundTag) : this() {
|
||||||
|
load(nbt)
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class Values(override val uuid: UUID) : IValues {
|
||||||
|
override var energy = Decimal.ZERO
|
||||||
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
parent?.isDirty = true
|
isDirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var passed = Decimal.ZERO
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
isDirty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override var received = Decimal.ZERO
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
isDirty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override val isServer: Boolean
|
||||||
|
get() = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private val data = Object2ObjectOpenHashMap<UUID, Values>()
|
||||||
|
|
||||||
|
fun values(uuid: UUID): Values {
|
||||||
|
return data.computeIfAbsent(uuid, Function { Values(uuid) })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun values(): Values {
|
||||||
|
return values(UUID.randomUUID())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun save(nbt: CompoundTag): CompoundTag {
|
||||||
|
for ((key, values) in data) {
|
||||||
|
nbt[key.toString()] = values.serialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
var passed: Decimal = passed
|
return nbt
|
||||||
set(value) {
|
}
|
||||||
if (field != value) {
|
|
||||||
field = value
|
|
||||||
parent?.isDirty = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var received: Decimal = received
|
fun load(nbt: CompoundTag) {
|
||||||
set(value) {
|
data.clear()
|
||||||
if (field != value) {
|
|
||||||
field = value
|
for (key in nbt.allKeys) {
|
||||||
parent?.isDirty = true
|
val id = UUID.fromString(key)
|
||||||
}
|
data[id] = Values(id).also { it.deserialize(nbt.getCompound(key)) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val clientData = Object2ObjectOpenHashMap<UUID, IValues>()
|
||||||
|
|
||||||
|
val serverData: Data by lazyPerServer {
|
||||||
|
it.overworld().dataStorage.computeIfAbsent(::Data, ::Data, "otm_$savedataID")
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class Power(private val stack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider {
|
private inner class Power(private val stack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider {
|
||||||
@ -87,7 +165,18 @@ class QuantumBatteryItem : Item {
|
|||||||
override val energyFlow: FlowDirection
|
override val energyFlow: FlowDirection
|
||||||
get() = FlowDirection.BI_DIRECTIONAL
|
get() = FlowDirection.BI_DIRECTIONAL
|
||||||
|
|
||||||
var data = Data()
|
var values: IValues = UnboundValues()
|
||||||
|
|
||||||
|
fun updateValues() {
|
||||||
|
if (!values.isServer && isServerThread()) {
|
||||||
|
values = serverData.values(stack.tag?.getUUIDSafe("id") ?: UUID.randomUUID().also { stack.tagNotNull["id"] = it })
|
||||||
|
} else if (isClientThread()) {
|
||||||
|
val id = stack.tag?.getUUIDSafe("id") ?: return
|
||||||
|
|
||||||
|
if (values.uuid != id)
|
||||||
|
values = clientData.computeIfAbsent(id, Function { UnboundValues(it) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun <T : Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
override fun <T : Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||||
if (cap == ForgeCapabilities.ENERGY || cap == MatteryCapability.ENERGY) {
|
if (cap == ForgeCapabilities.ENERGY || cap == MatteryCapability.ENERGY) {
|
||||||
@ -100,253 +189,107 @@ class QuantumBatteryItem : Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
if (howMuch.isNegative) {
|
if (!howMuch.isPositive)
|
||||||
return Decimal.ZERO
|
return Decimal.ZERO
|
||||||
}
|
|
||||||
|
|
||||||
if (data.parent == null && isServerThread()) {
|
updateValues()
|
||||||
determineQuantumLink()
|
|
||||||
|
|
||||||
if (data.parent == null) {
|
if (!values.isServer && !simulate)
|
||||||
return Decimal.ZERO
|
return Decimal.ZERO
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCreative) {
|
if (balanceValues == null) {
|
||||||
val newEnergy = (data.energy - howMuch).moreThanZero()
|
val newEnergy = (values.energy - howMuch).moreThanZero()
|
||||||
val diff = data.energy - newEnergy
|
val diff = values.energy - newEnergy
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
data.energy = newEnergy
|
values.energy = newEnergy
|
||||||
data.passed += diff
|
values.passed += diff
|
||||||
|
}
|
||||||
|
|
||||||
|
return diff
|
||||||
|
} else {
|
||||||
|
val newEnergy = (values.energy - howMuch.coerceAtMost(balanceValues.energyThroughput)).moreThanZero()
|
||||||
|
val diff = values.energy - newEnergy
|
||||||
|
|
||||||
|
if (!simulate) {
|
||||||
|
values.energy = newEnergy
|
||||||
|
values.passed += diff
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
}
|
}
|
||||||
|
|
||||||
val newEnergy = (data.energy - howMuch.coerceAtMost(throughput!!)).moreThanZero()
|
|
||||||
val diff = data.energy - newEnergy
|
|
||||||
|
|
||||||
if (!simulate) {
|
|
||||||
data.energy = newEnergy
|
|
||||||
data.passed += diff
|
|
||||||
}
|
|
||||||
|
|
||||||
return diff
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
if (howMuch.isNegative) {
|
if (!howMuch.isPositive)
|
||||||
return Decimal.ZERO
|
return Decimal.ZERO
|
||||||
}
|
|
||||||
|
|
||||||
if (data.parent == null && isServerThread()) {
|
updateValues()
|
||||||
determineQuantumLink()
|
|
||||||
|
|
||||||
if (data.parent == null) {
|
if (!values.isServer && !simulate)
|
||||||
return Decimal.ZERO
|
return Decimal.ZERO
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCreative) {
|
if (balanceValues == null) {
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
data.energy += howMuch
|
values.energy += howMuch
|
||||||
data.received += howMuch
|
values.received += howMuch
|
||||||
}
|
}
|
||||||
|
|
||||||
return howMuch
|
return howMuch
|
||||||
}
|
} else if (values.energy >= balanceValues.energyCapacity) {
|
||||||
|
|
||||||
if (data.energy >= capacity!!) {
|
|
||||||
return Decimal.ZERO
|
return Decimal.ZERO
|
||||||
|
} else {
|
||||||
|
val newEnergy = (values.energy + howMuch.coerceAtMost(balanceValues.energyThroughput)).coerceAtMost(balanceValues.energyCapacity)
|
||||||
|
val diff = newEnergy - values.energy
|
||||||
|
|
||||||
|
if (!simulate) {
|
||||||
|
values.energy = newEnergy
|
||||||
|
values.received += diff
|
||||||
|
}
|
||||||
|
|
||||||
|
return diff
|
||||||
}
|
}
|
||||||
|
|
||||||
val newEnergy = (data.energy + howMuch.coerceAtMost(throughput!!)).coerceAtMost(capacity!!)
|
|
||||||
val diff = newEnergy - data.energy
|
|
||||||
|
|
||||||
if (!simulate) {
|
|
||||||
data.energy = newEnergy
|
|
||||||
data.received += diff
|
|
||||||
}
|
|
||||||
|
|
||||||
return diff
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override var batteryLevel: Decimal
|
override var batteryLevel: Decimal
|
||||||
get() {
|
get() {
|
||||||
if (data.parent == null) {
|
updateValues()
|
||||||
determineQuantumLink()
|
return values.energy
|
||||||
}
|
|
||||||
|
|
||||||
if (isClientThread()) {
|
|
||||||
return clientPowerMap[data.index]?.energy ?: data.energy
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.energy
|
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
if (data.parent == null) {
|
updateValues()
|
||||||
determineQuantumLink()
|
values.energy = value
|
||||||
}
|
|
||||||
|
|
||||||
if (isClientThread()) {
|
|
||||||
val energy1 = clientPowerMap[data.index]
|
|
||||||
|
|
||||||
if (energy1 != null) {
|
|
||||||
energy1.energy = value
|
|
||||||
} else {
|
|
||||||
data.energy = value
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
data.energy = value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val passed: Decimal
|
val passed: Decimal get() {
|
||||||
get() {
|
updateValues()
|
||||||
if (data.parent == null) {
|
return values.passed
|
||||||
determineQuantumLink()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isClientThread()) {
|
|
||||||
return clientPowerMap[data.index]?.passed ?: data.passed
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.passed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val received: Decimal
|
val received: Decimal get() {
|
||||||
get() {
|
updateValues()
|
||||||
if (data.parent == null) {
|
return values.received
|
||||||
determineQuantumLink()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isClientThread()) {
|
|
||||||
return clientPowerMap[data.index]?.received ?: data.received
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.received
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val maxBatteryLevel: Decimal
|
override val maxBatteryLevel: Decimal
|
||||||
get() = capacity ?: (batteryLevel + Decimal.LONG_MAX_VALUE)
|
get() = balanceValues?.energyCapacity ?: (batteryLevel + Decimal.LONG_MAX_VALUE)
|
||||||
|
|
||||||
override val missingPower: Decimal
|
override val missingPower: Decimal
|
||||||
get() = if (isCreative) Decimal.LONG_MAX_VALUE else super.missingPower
|
get() = if (isCreative) Decimal.LONG_MAX_VALUE else super.missingPower
|
||||||
|
|
||||||
private fun determineQuantumLink() {
|
|
||||||
if (data.parent == null && isServerThread()) {
|
|
||||||
val existing = stack.tag?.getInt("link_id")
|
|
||||||
|
|
||||||
if (existing == null) {
|
|
||||||
val old = data
|
|
||||||
data = saveData!!.factorize()
|
|
||||||
data.energy = old.energy
|
|
||||||
stack.tagNotNull["link_id"] = data.index
|
|
||||||
} else {
|
|
||||||
data = saveData?.computeIfAbsent(existing) ?: Data(null, existing, data.energy, data.passed, data.received)
|
|
||||||
}
|
|
||||||
} else if (!isServerThread()) {
|
|
||||||
// client ?
|
|
||||||
val existing = stack.tag?.getInt("link_id") ?: return
|
|
||||||
|
|
||||||
if (existing != data.index) {
|
|
||||||
data = Data(data.parent, existing, data.energy, data.passed, data.received)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun determineQuantumLinkWeak() {
|
|
||||||
if (data.parent == null && isServerThread()) {
|
|
||||||
val existing = stack.tag?.getInt("link_id")
|
|
||||||
|
|
||||||
if (existing != null) {
|
|
||||||
data = saveData?.computeIfAbsent(existing) ?: Data(null, existing, data.energy, data.passed, data.received)
|
|
||||||
}
|
|
||||||
} else if (!isServerThread()) {
|
|
||||||
val existing = stack.tag?.getInt("link_id") ?: return
|
|
||||||
|
|
||||||
if (existing != data.index) {
|
|
||||||
data = Data(data.parent, existing, data.energy, data.passed, data.received)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val isCreative: Boolean
|
|
||||||
|
|
||||||
private val _capacity: () -> Decimal?
|
|
||||||
private val _throughput: () -> Decimal?
|
|
||||||
|
|
||||||
val capacity get() = _capacity.invoke()
|
|
||||||
val throughput get() = _throughput.invoke()
|
|
||||||
|
|
||||||
val saveDataID: String
|
|
||||||
|
|
||||||
val saveData: SavedCountingMap<Data>? get() {
|
|
||||||
if (isServerThread()) {
|
|
||||||
return MINECRAFT_SERVER.overworld().dataStorage.computeIfAbsent({
|
|
||||||
SavedCountingMap(Companion::storeValue, Companion::loadValue, ::Data).load(it)
|
|
||||||
}, {
|
|
||||||
SavedCountingMap(Companion::storeValue, Companion::loadValue, ::Data)
|
|
||||||
}, saveDataID) ?: throw NullPointerException("Unable to get save data for $this in ${MINECRAFT_SERVER.overworld()}")
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ClientData(
|
|
||||||
var energy: Decimal = Decimal.ZERO,
|
|
||||||
var passed: Decimal = Decimal.ZERO,
|
|
||||||
var received: Decimal = Decimal.ZERO,
|
|
||||||
)
|
|
||||||
|
|
||||||
val clientPowerMap: Int2ObjectOpenHashMap<ClientData> by lazy {
|
|
||||||
check(isClient) { "Invalid side" }
|
|
||||||
Int2ObjectOpenHashMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(saveDataID: String) : super(Properties().stacksTo(1).rarity(Rarity.EPIC)) {
|
|
||||||
isCreative = true
|
|
||||||
_capacity = { null }
|
|
||||||
_throughput = { null }
|
|
||||||
this.saveDataID = "otm_$saveDataID".intern()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(saveDataID: String, capacity: Decimal, io: Decimal) : super(Properties().stacksTo(1)) {
|
|
||||||
isCreative = false
|
|
||||||
_capacity = { capacity }
|
|
||||||
_throughput = { io }
|
|
||||||
this.saveDataID = "otm_$saveDataID".intern()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(saveDataID: String, values: EnergyBalanceValues) : super(Properties().stacksTo(1)) {
|
|
||||||
isCreative = false
|
|
||||||
_capacity = values::energyCapacity
|
|
||||||
_throughput = values::energyThroughput
|
|
||||||
this.saveDataID = "otm_$saveDataID".intern()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isBarVisible(p_150899_: ItemStack): Boolean {
|
override fun isBarVisible(p_150899_: ItemStack): Boolean {
|
||||||
if (isCreative)
|
if (isCreative) return false
|
||||||
return false
|
|
||||||
|
|
||||||
return p_150899_.matteryEnergy != null
|
return p_150899_.matteryEnergy != null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBarWidth(p_150900_: ItemStack): Int {
|
override fun getBarWidth(p_150900_: ItemStack): Int {
|
||||||
if (isCreative)
|
if (isCreative) return 13
|
||||||
return 13
|
|
||||||
|
|
||||||
return p_150900_.matteryEnergy?.getBarWidth() ?: super.getBarWidth(p_150900_)
|
return p_150900_.matteryEnergy?.getBarWidth() ?: super.getBarWidth(p_150900_)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBarColor(p_150901_: ItemStack): Int {
|
override fun getBarColor(p_150901_: ItemStack): Int {
|
||||||
if (isCreative)
|
if (isCreative) return 0
|
||||||
return 0
|
|
||||||
|
|
||||||
return p_150901_.matteryEnergy?.getBarColor() ?: super.getBarColor(p_150901_)
|
return p_150901_.matteryEnergy?.getBarColor() ?: super.getBarColor(p_150901_)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,29 +297,19 @@ class QuantumBatteryItem : Item {
|
|||||||
return Power(stack)
|
return Power(stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun appendHoverText(
|
override fun appendHoverText(itemStack: ItemStack, level: Level?, components: MutableList<Component>, flags: TooltipFlag) {
|
||||||
itemStack: ItemStack,
|
super.appendHoverText(itemStack, level, components, flags)
|
||||||
p_41422_: Level?,
|
|
||||||
components: MutableList<Component>,
|
|
||||||
p_41424_: TooltipFlag
|
|
||||||
) {
|
|
||||||
super.appendHoverText(itemStack, p_41422_, components, p_41424_)
|
|
||||||
|
|
||||||
val power = itemStack.getCapability(MatteryCapability.ENERGY).orThrow() as Power
|
val power = itemStack.getCapability(MatteryCapability.ENERGY).orThrow() as Power
|
||||||
|
power.updateValues()
|
||||||
|
|
||||||
components.add(TranslatableComponent("otm.item.quantum_description").withStyle(ChatFormatting.DARK_GRAY))
|
components.add(TranslatableComponent("otm.item.quantum_description").withStyle(ChatFormatting.DARK_GRAY))
|
||||||
|
|
||||||
if (isCreative) {
|
if (balanceValues == null) {
|
||||||
components.add(TranslatableComponent("otm.item.quantum_battery.creative_power", power.batteryLevel.formatPower()).withStyle(ChatFormatting.GRAY))
|
components.add(TranslatableComponent("otm.item.quantum_battery.creative_power", power.batteryLevel.formatPower()).withStyle(ChatFormatting.GRAY))
|
||||||
} else {
|
} else {
|
||||||
components.add(TranslatableComponent("otm.item.power.storage", power.batteryLevel.formatPower(), capacity!!.formatPower()).withStyle(ChatFormatting.GRAY))
|
components.add(TranslatableComponent("otm.item.power.storage", power.batteryLevel.formatPower(), balanceValues.energyCapacity.formatPower()).withStyle(ChatFormatting.GRAY))
|
||||||
|
components.add(TranslatableComponent("otm.item.power.throughput_mono", balanceValues.energyThroughput.formatPower()).withStyle(ChatFormatting.GRAY))
|
||||||
components.add(
|
|
||||||
TranslatableComponent(
|
|
||||||
"otm.item.power.throughput",
|
|
||||||
throughput!!.formatPower(),
|
|
||||||
throughput!!.formatPower()
|
|
||||||
).withStyle(ChatFormatting.GRAY))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
components.add(TranslatableComponent("otm.item.power.passed", power.passed.formatPower()).withStyle(ChatFormatting.GRAY))
|
components.add(TranslatableComponent("otm.item.power.passed", power.passed.formatPower()).withStyle(ChatFormatting.GRAY))
|
||||||
@ -387,18 +320,18 @@ class QuantumBatteryItem : Item {
|
|||||||
components.add(TranslatableComponent("otm.item.quantum_battery.creative2").withStyle(ChatFormatting.DARK_GRAY))
|
components.add(TranslatableComponent("otm.item.quantum_battery.creative2").withStyle(ChatFormatting.DARK_GRAY))
|
||||||
}
|
}
|
||||||
|
|
||||||
components.add(TranslatableComponent("otm.item.quantum_link_id", power.data.index).withStyle(ChatFormatting.DARK_GRAY))
|
components.add(TranslatableComponent("otm.item.quantum_link_id", power.values.uuid).withStyle(ChatFormatting.DARK_GRAY))
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun clientDisconnect(event: ClientPlayerNetworkEvent.LoggingOut) {
|
fun clientDisconnect(event: ClientPlayerNetworkEvent.LoggingOut) {
|
||||||
ForgeRegistries.ITEMS.values.stream().forEach { if (it is QuantumBatteryItem) it.clientPowerMap.clear() }
|
ForgeRegistries.ITEMS.values.forEach { if (it is QuantumBatteryItem) it.clientData.clear() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readPacket(buff: FriendlyByteBuf): ChargePacket {
|
fun readPacket(buff: FriendlyByteBuf): ChargePacket {
|
||||||
return ChargePacket(
|
return ChargePacket(
|
||||||
(ForgeRegistries.ITEMS as ForgeRegistry<Item>).getValue(buff.readInt()) as QuantumBatteryItem,
|
ForgeRegistries.ITEMS.getValue(buff.readInt()) as QuantumBatteryItem,
|
||||||
buff.readInt(),
|
buff.readUUID(),
|
||||||
buff.readDecimal(),
|
buff.readDecimal(),
|
||||||
buff.readDecimal(),
|
buff.readDecimal(),
|
||||||
buff.readDecimal(),
|
buff.readDecimal(),
|
||||||
@ -408,54 +341,33 @@ class QuantumBatteryItem : Item {
|
|||||||
fun tick(event: ServerTickEvent) {
|
fun tick(event: ServerTickEvent) {
|
||||||
if (event.phase == TickEvent.Phase.END) {
|
if (event.phase == TickEvent.Phase.END) {
|
||||||
for (ply in event.server.playerList.players) {
|
for (ply in event.server.playerList.players) {
|
||||||
val networkedChannels = IntOpenHashSet(0)
|
val networkedChannels = ObjectOpenHashSet<UUID>(0)
|
||||||
|
|
||||||
for (item in ply.allItemsStream().filter { !it.isEmpty && it.item is QuantumBatteryItem }) {
|
for (item in ply.allItems().filter { it.isNotEmpty && it.item is QuantumBatteryItem }) {
|
||||||
val power = item.getCapability(MatteryCapability.ENERGY).orThrow() as Power
|
val power = item.getCapability(MatteryCapability.ENERGY).orThrow() as Power
|
||||||
|
power.updateValues()
|
||||||
power.determineQuantumLinkWeak()
|
if (power.values.isServer && networkedChannels.add(power.values.uuid)) {
|
||||||
|
GenericNetworkChannel.send(ply, ChargePacket(item.item as QuantumBatteryItem, power.values.uuid, power.batteryLevel, power.passed, power.received))
|
||||||
if (power.data.index < 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkedChannels.add(power.data.index)) {
|
|
||||||
GenericNetworkChannel.send(ply, ChargePacket(item.item as QuantumBatteryItem, power.data.index, power.batteryLevel, power.data.passed, power.data.received))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadValue(parent: SavedCountingMap<Data>, tag: Tag, index: Int): Data {
|
|
||||||
if (tag is ByteArrayTag) {
|
|
||||||
return Data(parent, index, Decimal.deserializeNBT(tag))
|
|
||||||
} else if (tag is CompoundTag) {
|
|
||||||
return Data(parent, index, Decimal.deserializeNBT(tag["energy"]), Decimal.deserializeNBT(tag["passed"]), Decimal.deserializeNBT(tag["received"]))
|
|
||||||
} else {
|
|
||||||
return Data(parent, index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun storeValue(parent: SavedCountingMap<Data>, value: Data, index: Int): CompoundTag {
|
|
||||||
return CompoundTag().also {
|
|
||||||
it["energy"] = value.energy.serializeNBT()
|
|
||||||
it["passed"] = value.passed.serializeNBT()
|
|
||||||
it["received"] = value.received.serializeNBT()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChargePacket(
|
class ChargePacket(
|
||||||
val type: QuantumBatteryItem,
|
val type: QuantumBatteryItem,
|
||||||
val channel: Int,
|
override val uuid: UUID,
|
||||||
val energy: Decimal,
|
override var energy: Decimal,
|
||||||
val passed: Decimal,
|
override var passed: Decimal,
|
||||||
val received: Decimal,
|
override var received: Decimal,
|
||||||
) : MatteryPacket {
|
) : MatteryPacket, IValues {
|
||||||
|
override val isServer: Boolean
|
||||||
|
get() = false
|
||||||
|
|
||||||
override fun write(buff: FriendlyByteBuf) {
|
override fun write(buff: FriendlyByteBuf) {
|
||||||
buff.writeInt((ForgeRegistries.ITEMS as ForgeRegistry<Item>).getID(type))
|
buff.writeInt(ForgeRegistries.ITEMS.getID(type))
|
||||||
buff.writeInt(channel)
|
buff.writeUUID(uuid)
|
||||||
buff.writeDecimal(energy)
|
buff.writeDecimal(energy)
|
||||||
buff.writeDecimal(passed)
|
buff.writeDecimal(passed)
|
||||||
buff.writeDecimal(received)
|
buff.writeDecimal(received)
|
||||||
@ -463,7 +375,7 @@ class QuantumBatteryItem : Item {
|
|||||||
|
|
||||||
override fun play(context: Supplier<NetworkEvent.Context>) {
|
override fun play(context: Supplier<NetworkEvent.Context>) {
|
||||||
context.packetHandled = true
|
context.packetHandled = true
|
||||||
val data = type.clientPowerMap.computeIfAbsent(channel, Int2ObjectFunction { ClientData() })
|
val data = type.clientData.computeIfAbsent(uuid, Function { UnboundValues(it) })
|
||||||
data.energy = energy
|
data.energy = energy
|
||||||
data.passed = passed
|
data.passed = passed
|
||||||
data.received = received
|
data.received = received
|
||||||
|
@ -351,7 +351,7 @@ object MItems {
|
|||||||
|
|
||||||
val QUANTUM_BATTERY: QuantumBatteryItem by registry.register(MNames.QUANTUM_BATTERY) { QuantumBatteryItem(MNames.QUANTUM_BATTERY, ItemsConfig.Batteries.QUANTUM_BATTERY) }
|
val QUANTUM_BATTERY: QuantumBatteryItem by registry.register(MNames.QUANTUM_BATTERY) { QuantumBatteryItem(MNames.QUANTUM_BATTERY, ItemsConfig.Batteries.QUANTUM_BATTERY) }
|
||||||
val QUANTUM_CAPACITOR: QuantumBatteryItem by registry.register(MNames.QUANTUM_CAPACITOR) { QuantumBatteryItem(MNames.QUANTUM_CAPACITOR, ItemsConfig.Batteries.QUANTUM_CAPACITOR) }
|
val QUANTUM_CAPACITOR: QuantumBatteryItem by registry.register(MNames.QUANTUM_CAPACITOR) { QuantumBatteryItem(MNames.QUANTUM_CAPACITOR, ItemsConfig.Batteries.QUANTUM_CAPACITOR) }
|
||||||
val QUANTUM_BATTERY_CREATIVE: QuantumBatteryItem by registry.register(MNames.QUANTUM_BATTERY_CREATIVE) { QuantumBatteryItem(MNames.QUANTUM_BATTERY_CREATIVE) }
|
val QUANTUM_BATTERY_CREATIVE: QuantumBatteryItem by registry.register(MNames.QUANTUM_BATTERY_CREATIVE) { QuantumBatteryItem(MNames.QUANTUM_BATTERY_CREATIVE, null) }
|
||||||
val ZPM_BATTERY: ZPMItem by registry.register(MNames.ZPM_BATTERY) { ZPMItem() }
|
val ZPM_BATTERY: ZPMItem by registry.register(MNames.ZPM_BATTERY) { ZPMItem() }
|
||||||
val PROCEDURAL_BATTERY: ProceduralBatteryItem by registry.register(MNames.PROCEDURAL_BATTERY) { ProceduralBatteryItem() }
|
val PROCEDURAL_BATTERY: ProceduralBatteryItem by registry.register(MNames.PROCEDURAL_BATTERY) { ProceduralBatteryItem() }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user