diff --git a/build.gradle.kts b/build.gradle.kts index 88b8b4f17..25739d3b9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -141,9 +141,9 @@ dependencies { jarJar("ru.dbotthepony.kommons:kommons-gson:[$kommons_version,)") { setTransitive(false) } jarJar("ru.dbotthepony.kommons:kommons-guava:[$kommons_version,)") { setTransitive(false) } - implementation("ru.dbotthepony.kommons:kommons:[$kommons_version,)") { setTransitive(false) } - implementation("ru.dbotthepony.kommons:kommons-gson:[$kommons_version,)") { setTransitive(false) } - implementation("ru.dbotthepony.kommons:kommons-guava:[$kommons_version,)") { setTransitive(false) } + compileOnly("ru.dbotthepony.kommons:kommons:[$kommons_version,)") { setTransitive(false) } + compileOnly("ru.dbotthepony.kommons:kommons-gson:[$kommons_version,)") { setTransitive(false) } + compileOnly("ru.dbotthepony.kommons:kommons-guava:[$kommons_version,)") { setTransitive(false) } minecraftLibrary("ru.dbotthepony.kommons:kommons:[$kommons_version,)") { setTransitive(false) } minecraftLibrary("ru.dbotthepony.kommons:kommons-gson:[$kommons_version,)") { setTransitive(false) } diff --git a/gradle.properties b/gradle.properties index f8f2d4aae..4ba2fd72b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,7 @@ forge_version=48.1.0 mixingradle_version=0.7.33 mixin_version=0.8.5 -kommons_version=2.3.3 +kommons_version=2.9.13 jei_version=16.0.0.28 jupiter_version=5.9.2 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt index a681d2a20..0fc28fa04 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt @@ -5,18 +5,21 @@ import net.minecraft.nbt.CompoundTag import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.event.entity.living.LivingAttackEvent import net.minecraftforge.event.entity.living.LivingHurtEvent +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.core.nbt.set -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer import java.io.InputStream abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: MatteryPlayerCapability) : INBTSerializable { val ply get() = android.ply - val synchronizer = FieldSynchronizer() + val syncher = DelegateSyncher() + val syncherRemote = syncher.Remote() - open var level by synchronizer.int(setter = setter@{ value, field, setByRemote -> - if (value != field.read()) { - field.write(value) + open var level by syncher.int(setter = setter@{ field, value -> + if (value != field.get()) { + field.accept(value) applyModifiers() } }) @@ -28,7 +31,7 @@ abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: Matt * Called when it is required to network everything again */ open fun invalidateNetwork() { - synchronizer.invalidate() + syncherRemote.invalidate() } open fun applyModifiers() {} @@ -38,11 +41,11 @@ abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: Matt open fun onAttack(event: LivingAttackEvent) {} open fun collectNetworkPayload(): FastByteArrayOutputStream? { - return synchronizer.collectNetworkPayload() + return syncherRemote.write() } open fun applyNetworkPayload(stream: InputStream) { - synchronizer.read(stream) + syncher.read(stream) } override fun serializeNBT(): CompoundTag { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt index 563f0e293..35dd6c40d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt @@ -8,9 +8,11 @@ import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.player.Player import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.util.INBTSerializable -import net.minecraftforge.eventbus.api.Cancelable import net.minecraftforge.eventbus.api.Event import net.minecraftforge.eventbus.api.Event.HasResult +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.awareItemsStream @@ -19,7 +21,6 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.milliTime -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger import java.io.InputStream import kotlin.math.absoluteValue @@ -53,9 +54,10 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay val ply: Player get() = capability.ply - val synchronizer = FieldSynchronizer() + val syncher = DelegateSyncher() + val syncherRemote = syncher.Remote() - var isResearched by synchronizer.bool().property + var isResearched by syncher.boolean() private set var tag = CompoundTag() @@ -65,7 +67,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay * Called when it is required to network everything again */ fun invalidateNetwork() { - synchronizer.invalidate() + syncherRemote.invalidate() } fun unResearch() { @@ -187,11 +189,11 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay } fun collectNetworkPayload(): FastByteArrayOutputStream? { - return synchronizer.collectNetworkPayload() + return syncherRemote.write() } fun applyNetworkPayload(stream: InputStream) { - synchronizer.read(stream) + syncher.read(stream) } val canResearch: Boolean get() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchDescription.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchDescription.kt index 5c071f633..e5b2f2a81 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchDescription.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchDescription.kt @@ -7,6 +7,7 @@ import net.minecraft.ChatFormatting import net.minecraft.network.chat.Component import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.registries.DeferredRegister +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.client.ShiftPressedCond import ru.dbotthepony.mc.otm.config.AndroidConfig diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchResult.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchResult.kt index 06f430dd2..d83324d76 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchResult.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchResult.kt @@ -7,6 +7,7 @@ import net.minecraft.resources.ResourceLocation import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.registries.DeferredRegister import org.apache.logging.log4j.LogManager +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.core.getValue import ru.dbotthepony.mc.otm.data.SingletonCodec diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidSwitchableFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidSwitchableFeature.kt index 13ab36b84..6563b1066 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidSwitchableFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidSwitchableFeature.kt @@ -2,18 +2,21 @@ package ru.dbotthepony.mc.otm.android import net.minecraft.client.multiplayer.ClientLevel import net.minecraft.nbt.CompoundTag +import net.minecraft.server.level.ServerPlayer +import ru.dbotthepony.kommons.math.RGBAColor +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.minecraft -import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.nbt.set abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: MatteryPlayerCapability) : AndroidFeature(type, android) { - var isActive by synchronizer.bool(setter = setter@{ value, access, setByRemote -> - if (value != access.readBoolean()) { - access.write(value) + var isActive by syncher.boolean(setter = setter@{ access, value -> + if (value != access.get()) { + access.accept(value) - if (!setByRemote) { + if (ply is ServerPlayer) { if (value) { applyModifiers() } else { @@ -21,13 +24,13 @@ abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: Ma } } } - }).property + }) open val allowToSwitchByPlayer: Boolean get() = true open val allowToSwitchByPlayerWhileSpectator: Boolean get() = true open val maxCooldown: Int get() = 0 - open var cooldown by synchronizer.int().property + open var cooldown by syncher.int() val isOnCooldown: Boolean get() = maxCooldown > 0 && cooldown > 0 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt index a8b1dd50d..196470827 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt @@ -23,6 +23,7 @@ import net.minecraft.world.phys.shapes.Shapes import net.minecraftforge.client.event.RenderLevelStageEvent import net.minecraftforge.event.ForgeEventFactory import net.minecraftforge.event.entity.living.LivingDeathEvent +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.android.AndroidActiveFeature @@ -38,7 +39,6 @@ import ru.dbotthepony.mc.otm.config.AndroidConfig import ru.dbotthepony.mc.otm.core.genericPositions import ru.dbotthepony.mc.otm.core.holder import ru.dbotthepony.mc.otm.core.isFall -import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.math.asVector import ru.dbotthepony.mc.otm.core.math.component1 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ItemMagnetFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ItemMagnetFeature.kt index 1ddcd7f3b..bd0e622d1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ItemMagnetFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ItemMagnetFeature.kt @@ -4,6 +4,7 @@ import net.minecraft.client.multiplayer.ClientLevel import net.minecraft.network.FriendlyByteBuf import net.minecraft.world.entity.Entity import net.minecraft.world.entity.item.ItemEntity +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.config.AndroidConfig import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability @@ -13,7 +14,6 @@ import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.render.ResearchIcons import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid -import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.minus import ru.dbotthepony.mc.otm.core.math.plus import ru.dbotthepony.mc.otm.core.position diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/JumpBoostFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/JumpBoostFeature.kt index d92f68fbe..4d0a3a502 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/JumpBoostFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/JumpBoostFeature.kt @@ -3,6 +3,9 @@ package ru.dbotthepony.mc.otm.android.feature import net.minecraft.network.FriendlyByteBuf import net.minecraft.server.level.ServerPlayer import net.minecraft.sounds.SoundSource +import ru.dbotthepony.kommons.math.RGBAColor +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact @@ -11,7 +14,6 @@ import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.ResearchIcons import ru.dbotthepony.mc.otm.config.AndroidConfig import ru.dbotthepony.mc.otm.config.ClientConfig -import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.math.plus import ru.dbotthepony.mc.otm.network.GenericNetworkChannel @@ -55,13 +57,13 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF override val maxCooldown: Int get() = (AndroidConfig.JumpBoost.BASE_COOLDOWN - AndroidConfig.JumpBoost.COOLDOWN_REDUCTION * level).coerceAtLeast(0) - override var cooldown by synchronizer.int(setter = setter@{ value, access, setByRemote -> - access.write(value) + override var cooldown by syncher.int(setter = setter@{ access, value -> + access.accept(value) - if (setByRemote) { + if (ply !is ServerPlayer) { tickCooldownClient = false } - }).property + }) private var lastGround = false diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmorFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmorFeature.kt index 8dc1f81db..d51c19f5f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmorFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmorFeature.kt @@ -1,12 +1,11 @@ package ru.dbotthepony.mc.otm.android.feature import net.minecraft.nbt.CompoundTag -import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerPlayer import net.minecraftforge.event.entity.living.LivingHurtEvent -import ru.dbotthepony.mc.otm.OverdriveThatMatters +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.android.AndroidFeature -import ru.dbotthepony.mc.otm.android.AndroidResearchManager import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact import ru.dbotthepony.mc.otm.core.isBypassArmor @@ -19,17 +18,15 @@ import ru.dbotthepony.mc.otm.triggers.NanobotsArmorTrigger import kotlin.math.roundToInt class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) { - var strength by synchronizer.int( - setter = setter@{ - value, access, _ -> access.write(value.coerceIn(0 .. 3)) - } - ).property + var strength by syncher.int( + setter = setter@{ access, value -> access.accept(value.coerceIn(0 .. 3)) } + ) var speed: Int = 0 set(value) { field = value.coerceIn(0 .. 3) } private var ticksPassed = 0 - var layers by synchronizer.int().property + var layers by syncher.int() override fun tickServer() { if (layers < strength + 1 && android.androidEnergy.extractEnergyExact(ENERGY_PER_LAYER, true)) { @@ -65,7 +62,7 @@ class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(An } } - event.amount = event.amount - realAbsorbed + event.amount -= realAbsorbed (ply as ServerPlayer?)?.awardStat(StatNames.DAMAGE_ABSORBED, (realAbsorbed * 10f).roundToInt()) layers-- } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NightVisionFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NightVisionFeature.kt index ad3ead63a..18572422f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NightVisionFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NightVisionFeature.kt @@ -2,13 +2,13 @@ package ru.dbotthepony.mc.otm.android.feature import net.minecraft.world.effect.MobEffectInstance import net.minecraft.world.effect.MobEffects +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.ResearchIcons import ru.dbotthepony.mc.otm.config.AndroidConfig -import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.registry.AndroidFeatures class NightVisionFeature(android: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.NIGHT_VISION, android) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ShockwaveFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ShockwaveFeature.kt index fe37b9113..54751846d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ShockwaveFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ShockwaveFeature.kt @@ -17,7 +17,7 @@ import ru.dbotthepony.mc.otm.config.AndroidConfig import ru.dbotthepony.mc.otm.core.damageType import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid import ru.dbotthepony.mc.otm.core.getExplosionResistance -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.math.getEllipsoidBlockPositions import ru.dbotthepony.mc.otm.core.math.minus diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/StepAssistFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/StepAssistFeature.kt index 74a4f7a3b..ecfb5580f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/StepAssistFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/StepAssistFeature.kt @@ -6,7 +6,7 @@ import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.ResearchIcons -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.registry.AndroidFeatures import java.util.* diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/SwimBoostersFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/SwimBoostersFeature.kt index 3129d4a24..60d1b9ce6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/SwimBoostersFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/SwimBoostersFeature.kt @@ -7,7 +7,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.ResearchIcons import ru.dbotthepony.mc.otm.config.AndroidConfig -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.registry.AndroidFeatures import java.util.* diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt index b809eacba..a810816c3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt @@ -4,9 +4,8 @@ import com.google.common.collect.ImmutableList import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap 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.ObjectArraySet -import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import it.unimi.dsi.fastutil.objects.Reference2IntArrayMap import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap import net.minecraft.core.BlockPos @@ -37,12 +36,13 @@ import net.minecraftforge.event.level.ChunkWatchEvent import net.minecraftforge.event.level.LevelEvent import net.minecraftforge.event.server.ServerStoppingEvent import org.apache.logging.log4j.LogManager +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.util.Listenable import ru.dbotthepony.mc.otm.SERVER_IS_LIVE import ru.dbotthepony.mc.otm.block.INeighbourChangeListener import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage -import ru.dbotthepony.mc.otm.core.ISubscriptable import ru.dbotthepony.mc.otm.core.collect.WeakHashSet import ru.dbotthepony.mc.otm.core.get import ru.dbotthepony.mc.otm.core.immutableList @@ -56,9 +56,7 @@ import ru.dbotthepony.mc.otm.core.util.TickList import ru.dbotthepony.mc.otm.core.util.countingLazy import ru.dbotthepony.mc.otm.network.BlockEntitySyncPacket import ru.dbotthepony.mc.otm.network.GenericNetworkChannel -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer import ru.dbotthepony.mc.otm.once -import ru.dbotthepony.mc.otm.onceServer import ru.dbotthepony.mc.otm.sometimeServer import java.lang.ref.WeakReference import java.util.* @@ -79,7 +77,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc private val sidelessCaps = Reference2ObjectOpenHashMap, SidelessCap<*>>() protected val tickList = TickList() protected val blockStateChangesCounter = IntCounter() - protected val dirtyListeners = ISubscriptable.Impl() + protected val dirtyListeners = Listenable.Impl() private val waitForServerLevel = ArrayList<() -> Unit>() private val _droppableContainers = ObjectArraySet() @@ -129,9 +127,6 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc open fun tick() { tickList.tick() - - if (synchronizer.isNotEmpty) - synchronizeToPlayers(false) } /** @@ -181,7 +176,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc } } - interface SideListener : Supplier>, ISubscriptable> + interface SideListener : Supplier>, Listenable> inner class Side(val side: RelativeSide) { init { @@ -202,9 +197,9 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc } } - private val listeners = ISubscriptable.Impl>() + private val listeners = Listenable.Impl>() - override fun addListener(listener: Consumer>): ISubscriptable.L { + override fun addListener(listener: Consumer>): Listenable.L { val l = listeners.addListener(listener) if (level is ServerLevel) listener.accept(value) return l @@ -488,30 +483,8 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc dirtyListeners.accept(Unit) } - val synchronizer = FieldSynchronizer { - if (isSynchronizing || tickList.ticks != 0) - return@FieldSynchronizer - - if (isRemoved) markSynchronizerClean() - - if (level?.isClientSide == false && (_subCache == null || (_subCache ?: throw ConcurrentModificationException()).players.isNotEmpty())) { - onceServer { - if (!isRemoved) { - synchronizeToPlayers(true) - } - } - } else { - markSynchronizerClean() - } - } - - private fun markSynchronizerClean() { - synchronizer.markClean() - } - - init { - synchronizer.defaultEndpoint.markUnused() - } + val syncher = DelegateSyncher() + private val synchers = Object2ObjectArrayMap() override fun setLevel(level: Level) { val old = this.level @@ -595,51 +568,29 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc return subs } - private fun synchronizeToPlayers(calledBySynchronizer: Boolean) { - isSynchronizing = true - - try { - check(level is ServerLevel) { "Invalid realm or Level is null" } - synchronizer.observe() - val subscription = subscription - - if (subscription.players.isNotEmpty() && (playerListUpdated || synchronizer.isDirty)) { - playerListUpdated = false - - for (player in subscription.players) { - if (player !in subscription.veto) { - val payload = synchronizer.computeEndpointFor(player).collectNetworkPayload() - - if (payload != null) { - GenericNetworkChannel.send(player, BlockEntitySyncPacket(blockPos, payload.array, payload.length)) - } - } - } - - synchronizer.markClean() - } else if (calledBySynchronizer) { - synchronizer.markClean() - } - } finally { - isSynchronizing = false - } - } - private class ChunkSubscribers(level: ServerLevel, val chunkPos: Long) { val level = WeakReference(level) val blockEntities = WeakHashSet(linked = true, initialCapacity = 0) val players = ObjectArraySet(0) val veto = ObjectArraySet(0) - val blockEntitiesWithObservers = WeakHashSet(linked = true, initialCapacity = 0) private val player2ResubCount = Reference2IntArrayMap() + private var isTicking = false + + private fun checkShouldTick() { + val shouldTick = blockEntities.isNotEmpty() && players.isNotEmpty() + + if (!shouldTick && isTicking) { + isTicking = false + tickingMap[level.get()]?.remove(this) + } else if (shouldTick && !isTicking) { + isTicking = true + tickingMap.computeIfAbsent(level.get()) { ArrayList() }.add(this) + } + } operator fun component1() = blockEntities operator fun component2() = players - val hasObservers: Boolean get() { - return blockEntities.any { it.synchronizer.hasObservers } - } - private fun recheckPlayer(player: ServerPlayer) { sometimeServer { if (player in players && !player.hasDisconnected()) { @@ -649,8 +600,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc veto.remove(player) blockEntities.forEach { - it.playerListUpdated = true - it.synchronizeToPlayers(false) + it.synchers[player] = it.syncher.Remote() } } } else if (player in players && player.hasDisconnected()) { @@ -663,6 +613,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc if (players.add(player)) { veto.add(player) recheckPlayer(player) + checkShouldTick() } else if (player !in veto) { player2ResubCount[player] = player2ResubCount.getInt(player) + 1 LOGGER.debug("{} got subscribed to {} without prior unsubscribing, forcefully resubscribing (this happened {} times)", player, ChunkPos(chunkPos), player2ResubCount.getInt(player)) @@ -674,15 +625,13 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc fun unsubscribe(player: ServerPlayer, normal: Boolean = true): Boolean { if (players.remove(player)) { veto.remove(player) + if (normal) player2ResubCount.removeInt(player) blockEntities.forEach { - it.synchronizer.removeEndpointFor(player) - } - - if (normal) { - player2ResubCount.removeInt(player) + it.synchers.remove(player) } + checkShouldTick() return true } @@ -690,27 +639,18 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc } fun subscribe(blockEntity: MatteryBlockEntity) { - if (!blockEntities.add(blockEntity)) return - - onceServer { - if (!blockEntity.isRemoved && blockEntity in blockEntities) { - blockEntity.synchronizeToPlayers(false) + if (blockEntities.add(blockEntity)) { + players.forEach { + if (it !in veto) { + blockEntity.synchers[it] = blockEntity.syncher.Remote() + } } } - - if (blockEntity.synchronizer.hasObservers && blockEntity.tickList.ticks == 0) { - blockEntitiesWithObservers.add(blockEntity) - - tickingMap - .computeIfAbsent(level.get() ?: throw NullPointerException("Level got GCd!")) { WeakHashSet(linked = true, initialCapacity = 2) } - .add(this) - } } fun unsubscribe(blockEntity: MatteryBlockEntity): Boolean { blockEntities.remove(blockEntity) - blockEntitiesWithObservers.remove(blockEntity) - + checkShouldTick() return players.isEmpty() && blockEntities.isEmpty() } @@ -743,7 +683,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc const val LOOT_TABLE_SEED_KEY = RandomizableContainerBlockEntity.LOOT_TABLE_SEED_TAG private val playerMap = WeakHashMap>() - private val tickingMap = WeakHashMap>() + private val tickingMap = WeakHashMap>() private val vec2Dir = Int2ObjectOpenHashMap() private val LOGGER = LogManager.getLogger() @@ -809,22 +749,20 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc fun postLevelTick(event: LevelTickEvent) { val level = event.level as? ServerLevel ?: return - val ticking = tickingMap[level] ?: return - ticking.removeIf { - val shouldRemove = it.blockEntitiesWithObservers.isEmpty() + tickingMap[level]?.forEach { + it.blockEntities.forEach { be -> + be.syncher.observe() - if (!shouldRemove && it.players.isNotEmpty()) { - it.blockEntitiesWithObservers.forEach { - it.synchronizeToPlayers(false) + be.synchers.entries.forEach { e -> + val (player, data) = e + val payload = data.write() + + if (payload != null) { + GenericNetworkChannel.send(player, BlockEntitySyncPacket(be.blockPos, payload.array, payload.length)) + } } } - - shouldRemove - } - - if (ticking.isEmpty()) { - tickingMap.remove(level) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt index 9eeab72a6..cbb233e24 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryDeviceBlockEntity.kt @@ -16,6 +16,8 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.fluids.FluidStack import net.minecraftforge.fluids.capability.IFluidHandler import net.minecraftforge.items.IItemHandler +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.capability.item.CombinedItemHandler import ru.dbotthepony.mc.otm.capability.item.EmptyItemHandler import ru.dbotthepony.mc.otm.capability.FlowDirection @@ -144,11 +146,11 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo savetables.bool(::automatePush, "fluid_${side}_push") } - var flow by synchronizer.enum(possibleModes, setter = { value, access, setByRemote -> + var flow by syncher.enum(possibleModes, setter = { access, value -> require(possibleModes.isSupertype(value)) { "Energy mode $value is not allowed (allowed modes: ${possibleModes.family})" } - if (access.read() != value) { - access.write(value) + if (access.get() != value) { + access.accept(value) markDirtyFast() if (value == FlowDirection.NONE) { @@ -180,13 +182,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo init { waitForServerLevel { - redstoneControl.addListener { - updateTickerState() - } - - neighbour.addListener { - updateTickerState() - } + redstoneControl.addListener(::updateTickerState) + neighbour.addListener(::updateTickerState) updateTickerState() } @@ -384,18 +381,13 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo savetables.bool(::automatePull, "energy_${side}_pull") savetables.bool(::automatePush, "energy_${side}_push") - dirtyListeners.addListener { + dirtyListeners.addListener(Runnable { updateTickerState() - } + }) waitForServerLevel { - redstoneControl.addListener { - updateTickerState() - } - - neighbour.addListener { - updateTickerState() - } + redstoneControl.addListener(::updateTickerState) + neighbour.addListener(::updateTickerState) updateTickerState() } @@ -443,11 +435,11 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo } } - override var energyFlow by synchronizer.enum(possibleModes, setter = { value, access, setByRemote -> + override var energyFlow by syncher.enum(possibleModes, setter = { access, value -> require(possibleModes.isSupertype(value)) { "Energy mode $value is not allowed (allowed modes: ${possibleModes.family})" } - if (access.read() != value) { - access.write(value) + if (access.get() != value) { + access.accept(value) markDirtyFast() if (value == FlowDirection.NONE) { @@ -462,7 +454,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo updateTickerState() } - }) + }).delegate fun invalidate(force: Boolean = false) { if (force) { @@ -611,11 +603,11 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo capController.close() } - var mode by synchronizer.enum(ItemHandlerMode.DISABLED, setter = { value, access, setByRemote -> + var mode by syncher.enum(ItemHandlerMode.DISABLED, setter = { access, value -> require(value in possibleViews) { "View type $value is not allowed (allowed views: $possibleViews)" } - if (access.read() != value) { - access.write(value) + if (access.get() != value) { + access.accept(value) markDirtyFast() if (value == ItemHandlerMode.DISABLED) { @@ -633,7 +625,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo ItemHandlerMode.BATTERY -> battery!! } } - }) + }).delegate var automatePull = false set(value) { @@ -671,13 +663,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo savetables.enum(::mode, "itemhandler_${side}_mode", ItemHandlerMode::valueOf) waitForServerLevel { - redstoneControl.addListener { - updateTickerState() - } - - neighbour.addListener { - updateTickerState() - } + redstoneControl.addListener(::updateTickerState) + neighbour.addListener(::updateTickerState) updateTickerState() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneControl.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneControl.kt index 04ff7785f..4a5bb03b9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneControl.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneControl.kt @@ -1,26 +1,27 @@ package ru.dbotthepony.mc.otm.block.entity -import it.unimi.dsi.fastutil.booleans.BooleanConsumer import net.minecraft.nbt.CompoundTag import net.minecraftforge.common.util.INBTSerializable -import ru.dbotthepony.mc.otm.core.IBooleanSubscriptable -import ru.dbotthepony.mc.otm.core.ISubscriptable +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.util.Listenable +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.core.nbt.mapString import ru.dbotthepony.mc.otm.core.nbt.set -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer +import java.util.function.Consumer interface IRedstoneControlled { val redstoneControl: AbstractRedstoneControl } -abstract class AbstractRedstoneControl : INBTSerializable, IBooleanSubscriptable { +abstract class AbstractRedstoneControl : INBTSerializable, Listenable { abstract var redstoneSetting: RedstoneSetting abstract var redstoneSignal: Int - protected val listeners = IBooleanSubscriptable.Impl() + protected val listeners = Listenable.Impl() val isBlockedByRedstone: Boolean get() = !redstoneSetting.test(redstoneSignal) - final override fun addListener(listener: BooleanConsumer): ISubscriptable.L { + final override fun addListener(listener: Consumer): Listenable.L { return listeners.addListener(listener) } @@ -77,38 +78,32 @@ class RedstoneControl(private val valueChanges: (new: Boolean, old: Boolean) -> } class SynchronizedRedstoneControl( - synchronizer: FieldSynchronizer, + synchronizer: DelegateSyncher, private val valueChanges: (new: Boolean, old: Boolean) -> Unit, ) : AbstractRedstoneControl() { - override var redstoneSetting: RedstoneSetting by synchronizer.enum(RedstoneSetting.LOW, setter = { value, access, setByRemote -> - if (access.read() == value) return@enum - if (setByRemote) { - access.write(value) - } else { - val old = isBlockedByRedstone - access.write(value) - val state = isBlockedByRedstone + override var redstoneSetting: RedstoneSetting by synchronizer.enum(RedstoneSetting.LOW, setter = { access, value -> + if (access.get() == value) return@enum - if (state != old) { - valueChanges.invoke(state, old) - listeners.accept(state) - } + val old = isBlockedByRedstone + access.accept(value) + val state = isBlockedByRedstone + + if (state != old) { + valueChanges.invoke(state, old) + listeners.accept(state) } - }) + }).delegate - override var redstoneSignal: Int by synchronizer.int(0, setter = { value, access, setByRemote -> - if (access.readInt() == value) return@int - if (setByRemote) { - access.write(value) - } else { - val old = isBlockedByRedstone - access.write(value) - val state = isBlockedByRedstone + override var redstoneSignal: Int by synchronizer.int(0, setter = { access, value -> + if (access.get() == value) return@int - if (state != old) { - valueChanges.invoke(state, old) - listeners.accept(state) - } + val old = isBlockedByRedstone + access.accept(value) + val state = isBlockedByRedstone + + if (state != old) { + valueChanges.invoke(state, old) + listeners.accept(state) } - }).property + }).delegate } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt index a1e304372..fed7679f2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt @@ -9,7 +9,6 @@ import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Entity import net.minecraft.world.entity.EquipmentSlot import net.minecraft.world.entity.LivingEntity -import net.minecraft.world.entity.boss.wither.WitherBoss import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.player.Player import net.minecraft.world.level.Level @@ -20,7 +19,8 @@ import net.minecraft.world.level.levelgen.structure.BoundingBox import net.minecraft.world.phys.AABB import net.minecraft.world.phys.Vec3 import net.minecraftforge.common.Tags -import net.minecraftforge.registries.ForgeRegistries +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.BlackHoleBlock import ru.dbotthepony.mc.otm.block.entity.tech.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity @@ -37,6 +37,7 @@ import ru.dbotthepony.mc.otm.core.math.getSphericalBlockPositions import ru.dbotthepony.mc.otm.core.math.times import ru.dbotthepony.mc.otm.core.nbt.map import ru.dbotthepony.mc.otm.core.nbt.set +import ru.dbotthepony.mc.otm.core.util.decimal import ru.dbotthepony.mc.otm.matter.MatterManager import ru.dbotthepony.mc.otm.registry.MDamageTypes import ru.dbotthepony.mc.otm.registry.MatteryDamageSource @@ -46,9 +47,9 @@ import kotlin.math.roundToInt import kotlin.math.sqrt class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryBlockEntity(MBlockEntities.BLACK_HOLE, p_155229_, p_155230_) { - var mass by synchronizer.decimal(BASELINE_MASS, setter = setter@{ mass, field, setByRemote -> - if (setByRemote) { - field.write(mass) + var mass by syncher.decimal(BASELINE_MASS, setter = setter@{ field, mass -> + if (level !is ServerLevel) { + field.accept(mass) return@setter } @@ -57,19 +58,19 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery return@setter } - field.write(mass) + field.accept(mass) setChanged() updateGravStrength() }) - var gravitationStrength by synchronizer.double(1.0).property + var gravitationStrength by syncher.double(1.0).delegate private set var affectedBounds = BoundingBox(0, 0, 0, 1, 1, 1) private set var affectedBoundsAABB: AABB = AABB.of(affectedBounds) private set - var spinDirection by synchronizer.bool().property + var spinDirection by syncher.boolean().delegate private var sphereIterator: Iterator? = null private var sleepTicks = 4 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableBlockEntity.kt index 26817675e..8ab790400 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/cable/EnergyCableBlockEntity.kt @@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.block.entity.cable import net.minecraft.core.BlockPos import net.minecraft.core.Direction -import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.Level import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.entity.BlockEntityType @@ -23,6 +22,7 @@ import ru.dbotthepony.mc.otm.once import ru.dbotthepony.mc.otm.onceServer import java.util.Collections import java.util.EnumMap +import java.util.function.Consumer // after some thinking, team decided to settle with IC2's side (techreborn, gregtech, integrated dynamics*, pipez*, p2p tunnels, ...) of implementation, // where cables have no residue capacitance, and never pull/push energy by themselves @@ -50,7 +50,7 @@ abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockP init { waitForServerLevel { - neighbour.addListener { + neighbour.addListener(Consumer { if (isEnabled) { if (it.isPresent) { if (it.resolve().get() !is CableSide) { @@ -62,7 +62,7 @@ abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockP updateBlockState(blockRotation.side2Dir(side), it.isPresent || node.neighboursView[GraphNode.link(blockRotation.side2Dir(side))] != null) } } - } + }) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/FluidTankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/FluidTankBlockEntity.kt index b137b6ce1..110353896 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/FluidTankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/FluidTankBlockEntity.kt @@ -12,6 +12,7 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.fluids.FluidStack import net.minecraftforge.fluids.capability.IFluidHandler import org.apache.logging.log4j.LogManager +import ru.dbotthepony.kommons.util.ListenableDelegate import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.capability.item.CombinedItemHandler import ru.dbotthepony.mc.otm.capability.fluid.BlockMatteryFluidHandler @@ -27,15 +28,14 @@ import ru.dbotthepony.mc.otm.menu.decorative.FluidTankMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.FLUID_TANK, blockPos, blockState) { - val fluid = BlockMatteryFluidHandler(ItemsConfig::FLUID_TANK_CAPACITY, synchronizer.Field(FluidStack.EMPTY, FluidStackValueCodec, setter = { value, access, remote -> - access.write(value) - + val fluid = BlockMatteryFluidHandler(ItemsConfig::FLUID_TANK_CAPACITY, syncher.Slot(ListenableDelegate.SmartBox(FluidStack.EMPTY, setter = { access, value -> + access.accept(value) level?.lightEngine?.checkBlock(blockPos) - if (!remote) { + if (level is ServerLevel) { markDirtyFast() } - })) + }), FluidStackValueCodec)) val fillInput = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) val drainInput = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/HoloSignBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/HoloSignBlockEntity.kt index 1b1362ef7..52e650fb3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/HoloSignBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/HoloSignBlockEntity.kt @@ -3,12 +3,16 @@ package ru.dbotthepony.mc.otm.block.entity.decorative import net.minecraft.core.BlockPos import net.minecraft.nbt.CompoundTag import net.minecraft.network.chat.Component +import net.minecraft.server.level.ServerLevel import net.minecraft.world.MenuProvider import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.IRedstoneControlled import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.block.entity.SynchronizedRedstoneControl @@ -17,24 +21,23 @@ import ru.dbotthepony.mc.otm.core.math.component1 import ru.dbotthepony.mc.otm.core.math.component2 import ru.dbotthepony.mc.otm.core.math.component3 import ru.dbotthepony.mc.otm.menu.decorative.HoloSignMenu -import ru.dbotthepony.mc.otm.network.synchronizer.FloatFieldAccess import ru.dbotthepony.mc.otm.once import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlocks class HoloSignBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.HOLO_SIGN, blockPos, blockState), MenuProvider, IRedstoneControlled { - override val redstoneControl = SynchronizedRedstoneControl(synchronizer) { _, _ -> setChanged() } + override val redstoneControl = SynchronizedRedstoneControl(syncher) { _, _ -> setChanged() } - var signText by synchronizer.string("", setter = { value, access, remote -> + var signText by syncher.string("", setter = { access, value -> setChanged() - access.write(value) - }) + access.accept(value) + }).delegate - private fun colorSetter(value: Float, access: FloatFieldAccess, setByRemote: Boolean) { - if (access.readFloat() != value) { - access.write(value) + private fun colorSetter(access: Delegate, value: Float) { + if (access.get() != value) { + access.accept(value) - if (setByRemote) { + if (level !is ServerLevel) { markDirtyClientside() } else { markDirtyFast() @@ -47,10 +50,10 @@ class HoloSignBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryB minecraft.levelRenderer.setBlocksDirty(x, y, z, x, y, z) } - var textRed by synchronizer.float(1f, setter = ::colorSetter).property - var textGreen by synchronizer.float(1f, setter = ::colorSetter).property - var textBlue by synchronizer.float(85f / 255f, setter = ::colorSetter).property - var textAlpha by synchronizer.float(1f).property + var textRed by syncher.float(1f, setter = ::colorSetter).delegate + var textGreen by syncher.float(1f, setter = ::colorSetter).delegate + var textBlue by syncher.float(85f / 255f, setter = ::colorSetter).delegate + var textAlpha by syncher.float(1f).delegate var isLocked = false diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/InfiniteWaterSourceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/InfiniteWaterSourceBlockEntity.kt index 7a5e54219..57892f006 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/InfiniteWaterSourceBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/InfiniteWaterSourceBlockEntity.kt @@ -9,6 +9,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.registry.MBlockEntities +import java.util.function.Consumer class InfiniteWaterSourceBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.INFINITE_WATER_SOURCE, blockPos, blockState), IFluidHandler { override fun getTanks(): Int { @@ -55,7 +56,7 @@ class InfiniteWaterSourceBlockEntity(blockPos: BlockPos, blockState: BlockState) } } - tracker.addListener { ticker.isEnabled = it.isPresent } + tracker.addListener(Consumer { ticker.isEnabled = it.isPresent }) } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt index c0fa77ad3..a8e6df930 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt @@ -7,6 +7,9 @@ import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue +import ru.dbotthepony.kommons.util.value import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.BatteryBankBlockEntity import ru.dbotthepony.mc.otm.capability.FlowDirection @@ -22,7 +25,7 @@ import ru.dbotthepony.mc.otm.menu.matter.MatterCapacitorBankMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.MATTER_CAPACITOR_BANK, p_155229_, p_155230_), IMatterStorage { - var gaugeLevel by synchronizer.float().property + var gaugeLevel by syncher.float() private set val matterNode = SimpleMatterNode(matter = this) @@ -123,7 +126,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) val container = object : MatteryContainer(this::markDirtyFast, BatteryBankBlockEntity.CAPACITY) { override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) { super.setChanged(slot, new, old) - capacitorStatus[slot].boolean = new.getCapability(MatteryCapability.MATTER).isPresent + capacitorStatus[slot].value = new.getCapability(MatteryCapability.MATTER).isPresent gaugeLevel = storedMatter.percentage(maxStoredMatter) } @@ -147,7 +150,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) })) val capacitorStatus = immutableList(BatteryBankBlockEntity.CAPACITY) { - synchronizer.bool(false) + syncher.boolean(false) } init { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReconstructorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReconstructorBlockEntity.kt index 489a00ccc..2245711ed 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReconstructorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReconstructorBlockEntity.kt @@ -11,6 +11,8 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.registries.ForgeRegistries +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.MatteryCapability @@ -27,6 +29,7 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.UpgradeContainer import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.registryName +import ru.dbotthepony.mc.otm.core.util.item import ru.dbotthepony.mc.otm.graph.matter.MatterNode import ru.dbotthepony.mc.otm.matter.IMatterValue import ru.dbotthepony.mc.otm.matter.MatterManager @@ -43,7 +46,7 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState) private var lastItem: Item? = null private var initialDamage = 0.0 - var visualItemStack by synchronizer.item(observe = false) + var visualItemStack by syncher.item() private set var visualProgress = 0f diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt index e95210e30..bcc8d307e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt @@ -9,6 +9,8 @@ import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.JobContainer import ru.dbotthepony.mc.otm.block.entity.JobStatus import ru.dbotthepony.mc.otm.block.entity.ItemJob @@ -26,6 +28,7 @@ import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.UpgradeContainer import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.mc.otm.core.util.item import ru.dbotthepony.mc.otm.data.DecimalCodec import ru.dbotthepony.mc.otm.data.UUIDCodec import ru.dbotthepony.mc.otm.data.minRange @@ -142,10 +145,10 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : visualProgress = 0f } - var visualItemStack by synchronizer.item(observe = false) + var visualItemStack by syncher.item() private set - var visualProgress by synchronizer.float().property + var visualProgress by syncher.float() private set var renderRotation = 0f diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt index dc22e5692..baeadaa50 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt @@ -7,6 +7,8 @@ import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.JobContainer import ru.dbotthepony.mc.otm.block.entity.JobStatus import ru.dbotthepony.mc.otm.block.entity.ItemJob @@ -21,6 +23,7 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.container.UpgradeContainer +import ru.dbotthepony.mc.otm.core.util.item import ru.dbotthepony.mc.otm.menu.matter.MatterScannerMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.graph.matter.MatterNode @@ -162,10 +165,10 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : visualProgress = 0f } - var visualItemStack by synchronizer.item(observe = false) + var visualItemStack by syncher.item() private set - var visualProgress by synchronizer.float().property + var visualProgress by syncher.float() private set override fun onJobTick(status: JobStatus, id: Int) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt index ca660924f..43d369993 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt @@ -21,6 +21,7 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.storage.optics.priority import ru.dbotthepony.mc.otm.storage.optics.powered import ru.dbotthepony.mc.otm.storage.optics.flow +import java.util.function.Consumer class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.DRIVE_RACK, blockPos, blockState) { override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, MachinesConfig.DRIVE_RACK)) @@ -67,9 +68,9 @@ class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery savetables.int(::extractPriority) savetables.enum(::mode, map = FlowDirection::valueOf) - redstoneControl.addListener { + redstoneControl.addListener(Consumer { cell.isDetached = it - } + }) } override fun setLevel(level: Level) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt index b3a21ef86..03a2ea81e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt @@ -34,6 +34,7 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.storage.* import java.math.BigInteger import java.util.* +import java.util.function.Consumer import java.util.stream.Stream private data class SlotTuple(val slot: Int, val stack: ItemStack) @@ -101,24 +102,24 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter savetables.int(::extractPriority) exposeGlobally(MatteryCapability.STORAGE_NODE, cell) { it != RelativeSide.FRONT } - side(RelativeSide.FRONT).track(ForgeCapabilities.ITEM_HANDLER).addListener { + side(RelativeSide.FRONT).track(ForgeCapabilities.ITEM_HANDLER).addListener(Consumer { component?.let(cell::removeStorageComponent) component = if (it.isPresent) { ItemHandlerComponent(it.orThrow()).also { if (!redstoneControl.isBlockedByRedstone) cell.addStorageComponent(it) } } else { null } - } + }) - redstoneControl.addListener { - val component = component ?: return@addListener + redstoneControl.addListener(Consumer { + val component = component ?: return@Consumer if (it) { cell.removeStorageComponent(component) } else { cell.addStorageComponent(component) } - } + }) } val filter = ItemFilter(MAX_FILTERS) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt index 404a0fa31..b2b69e2b1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/AbstractPoweredFurnaceBlockEntity.kt @@ -14,6 +14,8 @@ import net.minecraft.world.item.crafting.SmokingRecipe import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.ForgeCapabilities +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage import ru.dbotthepony.mc.otm.block.entity.JobContainer import ru.dbotthepony.mc.otm.block.entity.JobStatus @@ -32,7 +34,9 @@ import ru.dbotthepony.mc.otm.container.UpgradeContainer import ru.dbotthepony.mc.otm.container.balance import ru.dbotthepony.mc.otm.core.collect.filter import ru.dbotthepony.mc.otm.core.collect.maybe +import ru.dbotthepony.mc.otm.core.getValue import ru.dbotthepony.mc.otm.core.immutableList +import ru.dbotthepony.mc.otm.core.util.item import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu import ru.dbotthepony.mc.otm.recipe.MatteryCookingRecipe import ru.dbotthepony.mc.otm.recipe.MicrowaveRecipe @@ -60,9 +64,9 @@ sealed class AbstractPoweredFurnaceBlockEntity

() /** * For data to be stored to and loaded from NBT automatically @@ -219,8 +233,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial /** * Whenever player has Exopack */ - var hasExopack by publicSynchronizer.bool(setter = setter@{ value, access, _ -> - access.write(value) + var hasExopack by publicSyncher.boolean(setter = setter@{ access, value -> + access.accept(value) _exoPackMenu = null if (value && ply is ServerPlayer) { @@ -228,32 +242,34 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial ExopackObtainedTrigger.trigger(ply) } } - }).property + }) /** * Whenever to render Exopack on player */ - var isExopackVisible by publicSynchronizer.bool(true).property + var isExopackVisible by publicSyncher.boolean(true) /** * Whenever to render Exopack glow in dark */ - var exopackGlows by publicSynchronizer.bool(true).property + var exopackGlows by publicSyncher.boolean(true) - var exopackColor by publicSynchronizer.Field(null, RGBCodec.nullable) + var exopackColor by publicSyncher.add(ListenableDelegate.Box(null), RGBCodec.nullable) /** * Tick event schedulers */ val tickList = TickList() - private val exopackSlotModifierMap: MutableMap by synchronizer.Map( + // kotlin moment + private fun _recomputeModifiers() { + exopackSlotModifier.recompute() + } + + private val exopackSlotModifierMap = syncher.MapSlot( + ListenableMap().also { it.addListener(Runnable { _recomputeModifiers() }) }, keyCodec = UUIDValueCodec, valueCodec = IntValueCodec, - backingMap = HashMap(), - callback = { - this.exopackSlotModifier.recompute() - }, ) /** @@ -267,16 +283,16 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } else { exopackContainer = PlayerMatteryContainer(it) } - }, backingMap = this.exopackSlotModifierMap) + }, backingMap = this.exopackSlotModifierMap.delegate) val regularSlotFilters = immutableList(Inventory.INVENTORY_SIZE) { - synchronizer.Field(null, ItemValueCodec.nullable) + syncher.add(null, ItemValueCodec.nullable) } - val slotsChargeFlag by synchronizer.Set( - codec = VarIntValueCodec, - backingSet = IntAVLTreeSet(), - ) + val slotsChargeFlag = syncher.SetSlot( + ListenableSet(IntAVLTreeSet()), + VarIntValueCodec, + ).delegate private fun slotChargeToDefault() { // броня @@ -311,7 +327,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } value.deserializeNBT(field.serializeNBT()) - value.addFilterSynchronizer(synchronizer) + value.addFilterSynchronizer(syncher) field = value _combinedInventory = null @@ -373,9 +389,9 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial /** * Whenever Exopack has 3x3 crafting grid upgrade installed */ - var isExopackCraftingUpgraded by publicSynchronizer.bool(setter = setter@{ value, access, _ -> - if (value != access.readBoolean()) { - access.write(value) + var isExopackCraftingUpgraded by publicSyncher.boolean(setter = setter@{ access, value -> + if (value != access.get()) { + access.accept(value) _exoPackMenu = null if (value && ply is ServerPlayer) { @@ -384,11 +400,11 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } } } - }).property + }) - var isExopackEnderAccessInstalled by publicSynchronizer.bool(setter = setter@{ value, access, _ -> - if (value != access.readBoolean()) { - access.write(value) + var isExopackEnderAccessInstalled by publicSyncher.boolean(setter = setter@{ access, value -> + if (value != access.get()) { + access.accept(value) _exoPackMenu = null if (value && ply is ServerPlayer) { @@ -397,7 +413,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } } } - }).property + }) private var _exoPackMenu: ExopackInventoryMenu? = null set(value) { @@ -441,11 +457,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial private var nextDischargeHurt = 20 private var nextHealTick = 0 - // players tracking us - // stored separately because EntityTracker and ChunkMup, etc are buried deep and - // getting them unburied will be a very work intense task - private val trackingPlayers = Reference2ObjectOpenHashMap() - /** * This returns if player is an Android or will become one on death/sleep/etc */ @@ -471,7 +482,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial /** * Whenever player should become an Android once transformation conditions are met (e.g. player dies or sleeps in bed) */ - var willBecomeAndroid by publicSynchronizer.bool().property + var willBecomeAndroid by publicSyncher.boolean() /** * Whenever player is an Android @@ -487,14 +498,14 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial * * Android-immune (de)buffs are specified in `data/overdrive_that_matters/tags/mob_effect/android_immune_effects.json` */ - var isAndroid by publicSynchronizer.bool().property + var isAndroid by publicSyncher.boolean() /** * Whenever player has exosuit smelting upgrade */ - var isExopackSmeltingInstalled by synchronizer.bool(setter = { value, access, _ -> - if (value != access.readBoolean()) { - access.write(value) + var isExopackSmeltingInstalled by syncher.boolean(setter = { access, value -> + if (value != access.get()) { + access.accept(value) _exoPackMenu = null if (value && ply is ServerPlayer) { @@ -503,7 +514,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } } } - }).property + }) inner class SmelterBelt(index: Int) : MachineJobEventLoop(ItemJob.CODEC) { override val energy: IMatteryEnergyStorage @@ -568,12 +579,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial /** * [IMatteryEnergyStorage] instance, representing Android' battery charge */ - val androidEnergy = BatteryBackedEnergyStorage(ply, synchronizer, AndroidConfig.ANDROID_MAX_ENERGY, AndroidConfig.ANDROID_MAX_ENERGY, true) + val androidEnergy = BatteryBackedEnergyStorage(ply, syncher, AndroidConfig.ANDROID_MAX_ENERGY, AndroidConfig.ANDROID_MAX_ENERGY, true) /** * [IMatteryEnergyStorage] instance, representing Exopack battery charge */ - val exopackEnergy = ProfiledEnergyStorage(BatteryBackedEnergyStorage(ply, synchronizer, Decimal.ZERO, ExopackConfig.ENERGY_CAPACITY, false, onChange = { for (v in smelters) v.notify(MachineJobEventLoop.IdleReason.POWER) })) + val exopackEnergy = ProfiledEnergyStorage(BatteryBackedEnergyStorage(ply, syncher, Decimal.ZERO, ExopackConfig.ENERGY_CAPACITY, false, onChange = { for (v in smelters) v.notify(MachineJobEventLoop.IdleReason.POWER) })) val exopackChargeSlots = MatteryContainer(4) @@ -604,7 +615,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial savetables.float(::exopackSmelterExperience, "exoPackSmelterExperience") savetables.bool(::isExopackSmeltingInstalled, "isExoPackSmeltingInstalled") - savetables.codecNullable(::exopackColor, RGBAColor.CODECRGB) + savetables.codecNullable(::exopackColor, RGBColorDFUCodec) savetables.bool(::exopackGlows) savetables.stateful(::sortingSettings) @@ -612,8 +623,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } fun invalidateNetworkState() { - synchronizer.invalidate() - publicSynchronizer.invalidate() + privateSyncherRemote.invalidate() + remoteSynchers.values.forEach { it.invalidate() } for (instance in research.values) { instance.invalidateNetwork() @@ -982,7 +993,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial override fun deserializeNBT(tag: CompoundTag) { savetables.deserializeNBT(tag) - if (MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON.uuid(ItemStack.EMPTY) in exopackSlotModifierMap) { + if (MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON.uuid(ItemStack.EMPTY) in exopackSlotModifierMap.delegate) { isExopackEnderAccessInstalled = true } @@ -1318,28 +1329,28 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial tickedOnce = true - val payload = synchronizer.collectNetworkPayload() + val payload = privateSyncherRemote.write() if (payload != null) { MatteryPlayerNetworkChannel.send(ply, MatteryPlayerFieldPacket(payload, false)) } - val trackingIterator = trackingPlayers.entries.iterator() + val trackingIterator = remoteSynchers.entries.iterator() - for ((ply, endpoint) in trackingIterator) { + for ((ply, remote) in trackingIterator) { if (ply.hasDisconnected()) { trackingIterator.remove() continue } - val payload2 = endpoint.collectNetworkPayload() + val payload2 = remote.write() if (payload2 != null) { MatteryPlayerNetworkChannel.send(ply, MatteryPlayerFieldPacket(payload2, true, this.ply.uuid)) } } - val payload3 = publicSynchronizer.collectNetworkPayload() + val payload3 = publicSyncherRemote.write() if (payload3 != null) { MatteryPlayerNetworkChannel.send(ply, MatteryPlayerFieldPacket(payload3, true)) @@ -1751,14 +1762,14 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial fun onStartTracking(event: PlayerEvent.StartTracking) { if (event.target is ServerPlayer) { event.target.matteryPlayer?.let { - it.trackingPlayers[event.entity as ServerPlayer] = it.publicSynchronizer.Endpoint() + it.remoteSynchers[event.entity as ServerPlayer] = it.publicSyncher.Remote() } } } fun onStopTracking(event: PlayerEvent.StopTracking) { if (event.target is ServerPlayer) { - event.target.matteryPlayer?.trackingPlayers?.remove(event.entity as ServerPlayer) + event.target.matteryPlayer?.remoteSynchers?.remove(event.entity as ServerPlayer) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BatteryBackedEnergyStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BatteryBackedEnergyStorage.kt index a39770a12..f43df3712 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BatteryBackedEnergyStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BatteryBackedEnergyStorage.kt @@ -7,6 +7,9 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.ticks.ContainerSingleItem import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.INBTSerializable +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.extractEnergy import ru.dbotthepony.mc.otm.capability.receiveEnergy @@ -15,14 +18,15 @@ import ru.dbotthepony.mc.otm.core.math.getDecimal import ru.dbotthepony.mc.otm.core.nbt.getItemStack import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.core.nbt.set -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer +import ru.dbotthepony.mc.otm.core.util.decimal +import ru.dbotthepony.mc.otm.core.util.observedItem import ru.dbotthepony.mc.otm.registry.StatNames import ru.dbotthepony.mc.otm.triggers.AndroidBatteryTrigger import ru.dbotthepony.mc.otm.triggers.ExopackBatterySlotTrigger class BatteryBackedEnergyStorage( private val ply: Player, - synchronizer: FieldSynchronizer, + synchronizer: DelegateSyncher, initialCharge: Decimal, maxCharge: Decimal, val isAndroid: Boolean, @@ -34,8 +38,8 @@ class BatteryBackedEnergyStorage( private var battery by synchronizer.decimal(initialCharge) private var maxBattery by synchronizer.decimal(maxCharge) - var item by synchronizer.item(setter = setter@{ value, access, _ -> - access.write(value) + var item by synchronizer.observedItem(setter = setter@{ access, value -> + access.accept(value) if (ply is ServerPlayer && isAndroid) { AndroidBatteryTrigger.trigger(ply, value) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IMatteryEnergyStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IMatteryEnergyStorage.kt index ffd4e221d..d01d7d0fd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IMatteryEnergyStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/IMatteryEnergyStorage.kt @@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.capability.energy import net.minecraftforge.energy.IEnergyStorage import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.core.math.Decimal -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import java.math.BigInteger import kotlin.math.roundToInt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/fluid/BlockMatteryFluidHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/fluid/BlockMatteryFluidHandler.kt index b93252b1a..0851929d6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/fluid/BlockMatteryFluidHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/fluid/BlockMatteryFluidHandler.kt @@ -5,15 +5,17 @@ import net.minecraft.world.item.BlockItem import net.minecraft.world.item.ItemStack import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.fluids.FluidStack +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.tagNotNull -import ru.dbotthepony.mc.otm.network.synchronizer.IMutableField import java.util.function.IntSupplier /** * Fluid handler for blocks */ -open class BlockMatteryFluidHandler(private val _capacity: IntSupplier, field: IMutableField) : AbstractMatteryFluidHandler(), INBTSerializable { +open class BlockMatteryFluidHandler(private val _capacity: IntSupplier, field: Delegate) : AbstractMatteryFluidHandler(), INBTSerializable { override var fluid by field override val capacity: Int diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt index 196389911..34096e6b6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IMatterStorage.kt @@ -4,7 +4,7 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.core.math.Decimal -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.orNull import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import kotlin.math.roundToInt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IPatternStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IPatternStorage.kt index 0eecae475..0c2f26341 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IPatternStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/IPatternStorage.kt @@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.capability.matter import net.minecraft.world.item.Item import net.minecraftforge.common.capabilities.ICapabilityProvider import ru.dbotthepony.mc.otm.capability.MatteryCapability -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.orNull import java.util.* import java.util.function.Predicate diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidAbilityKeyMapping.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidAbilityKeyMapping.kt index d3301a692..3fd14d90f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidAbilityKeyMapping.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidAbilityKeyMapping.kt @@ -12,7 +12,7 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.render.is3DContext -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.network.ActivateAndroidFeaturePacket import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel import kotlin.math.roundToInt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidMenuKeyMapping.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidMenuKeyMapping.kt index f81bd9c01..0ac414113 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidMenuKeyMapping.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidMenuKeyMapping.kt @@ -16,7 +16,7 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.drawArc -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.angleDifference import ru.dbotthepony.mc.otm.core.math.normalizeAngle import ru.dbotthepony.mc.otm.core.util.formatTickDuration diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt index 4588b2b7c..5cb58196d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt @@ -31,7 +31,7 @@ import ru.dbotthepony.mc.otm.client.render.sprites.MatteryAtlas import ru.dbotthepony.mc.otm.client.render.sprites.MatterySprite import ru.dbotthepony.mc.otm.config.ClientConfig import ru.dbotthepony.mc.otm.core.TextComponent -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.util.formatPower import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.registry.AndroidFeatures diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/FontRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/FontRenderer.kt index e5b7d8a1d..a98bca877 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/FontRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/FontRenderer.kt @@ -9,7 +9,7 @@ import net.minecraft.network.chat.Component import net.minecraft.util.FormattedCharSequence import org.joml.Matrix4f import ru.dbotthepony.mc.otm.core.FloatSupplier -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.component1 import ru.dbotthepony.mc.otm.core.math.component2 import ru.dbotthepony.mc.otm.core.math.component3 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/IGUIRenderable.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/IGUIRenderable.kt index e73213175..7b235d267 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/IGUIRenderable.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/IGUIRenderable.kt @@ -1,7 +1,7 @@ package ru.dbotthepony.mc.otm.client.render import net.minecraft.world.item.ItemStack -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor interface IGUIRenderable { /** diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/MGUIGraphics.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/MGUIGraphics.kt index 3c2dcc7a9..6d15bd0d4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/MGUIGraphics.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/MGUIGraphics.kt @@ -10,7 +10,7 @@ import net.minecraft.resources.ResourceLocation import net.minecraft.util.FormattedCharSequence import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.client.minecraft -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import kotlin.math.PI import kotlin.math.roundToInt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderExtensions.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderExtensions.kt index 1d08afc62..98d6442e5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderExtensions.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderExtensions.kt @@ -6,8 +6,8 @@ import com.mojang.blaze3d.vertex.VertexConsumer import net.minecraft.core.Vec3i import org.joml.Matrix4f import org.joml.Vector3f +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.IAngle -import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.math.rotateAroundPoint import ru.dbotthepony.mc.otm.core.math.rotateAroundThis diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderHelper.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderHelper.kt index 806da8d41..f5f3b0a83 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderHelper.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderHelper.kt @@ -14,9 +14,9 @@ import org.apache.logging.log4j.LogManager import org.joml.Matrix4f import org.lwjgl.opengl.GL11.GL_ALWAYS import org.lwjgl.opengl.GL11.GL_LESS +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.client.minecraft -import ru.dbotthepony.mc.otm.core.math.RGBAColor import java.util.* import kotlin.collections.ArrayDeque import kotlin.math.PI diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BankRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BankRenderer.kt index 07969b2b0..a4ae73899 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BankRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BankRenderer.kt @@ -22,18 +22,19 @@ import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.get import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.rotate import ru.dbotthepony.mc.otm.core.math.rotateY import ru.dbotthepony.mc.otm.nanoTime import java.util.function.BooleanSupplier +import java.util.function.Supplier import kotlin.math.PI abstract class BankRenderer(private val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer { protected abstract fun gaugeLevel(entity: T): Float protected abstract val texture: AbstractMatterySprite protected abstract val models: List - protected abstract fun status(entity: T): List + protected abstract fun status(entity: T): List> private val random = XoroshiroRandomSource(nanoTime) @@ -53,7 +54,7 @@ abstract class BankRenderer(private val context: B stack.translate(-0.5f, -0.5f, -0.5f) for ((i, model) in models.withIndex()) { - if (!status[i].asBoolean) { + if (!status[i].get()) { continue } @@ -124,7 +125,7 @@ class BatteryBankRenderer(context: BlockEntityRendererProvider.Context) : BankRe } } - override fun status(entity: BatteryBankBlockEntity): List { + override fun status(entity: BatteryBankBlockEntity): List> { return entity.batteryStatus } @@ -151,7 +152,7 @@ class MatterBatteryBankRenderer(context: BlockEntityRendererProvider.Context) : } } - override fun status(entity: MatterCapacitorBankBlockEntity): List { + override fun status(entity: MatterCapacitorBankBlockEntity): List> { return entity.capacitorStatus } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BlackHoleRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BlackHoleRenderer.kt index f47dd49e4..770ef3d96 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BlackHoleRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BlackHoleRenderer.kt @@ -18,7 +18,7 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.client.ShiftPressedCond import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.render.* -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.VECTOR_FORWARD import ru.dbotthepony.mc.otm.core.math.VECTOR_RIGHT import ru.dbotthepony.mc.otm.core.math.VECTOR_UP diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/EnergyCounterRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/EnergyCounterRenderer.kt index e67110f66..f33411fd2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/EnergyCounterRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/EnergyCounterRenderer.kt @@ -11,7 +11,7 @@ import ru.dbotthepony.mc.otm.block.entity.tech.EnergyCounterBlockEntity import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.core.TextComponent -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.asAngle import ru.dbotthepony.mc.otm.core.util.formatPower import ru.dbotthepony.mc.otm.core.math.times diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/FluidTankRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/FluidTankRenderer.kt index 7791ebc1e..3328df276 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/FluidTankRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/FluidTankRenderer.kt @@ -19,7 +19,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.core.ifPresentK -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.linearInterpolation import ru.dbotthepony.mc.otm.registry.MBlocks diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/GravitationStabilizerRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/GravitationStabilizerRenderer.kt index 60e1b97f4..2b6136717 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/GravitationStabilizerRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/GravitationStabilizerRenderer.kt @@ -20,7 +20,7 @@ import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.VECTOR_DOWN import ru.dbotthepony.mc.otm.core.math.VECTOR_FORWARD import ru.dbotthepony.mc.otm.core.math.VECTOR_RIGHT diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/HoloSignRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/HoloSignRenderer.kt index 92ed47869..e69a067e1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/HoloSignRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/HoloSignRenderer.kt @@ -11,7 +11,7 @@ import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.draw import ru.dbotthepony.mc.otm.core.get import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.rotateWithBlockFacing class HoloSignRenderer(private val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/sprites/AbstractMatterySprite.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/sprites/AbstractMatterySprite.kt index 09013d598..a65fc4dce 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/sprites/AbstractMatterySprite.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/sprites/AbstractMatterySprite.kt @@ -12,13 +12,13 @@ import net.minecraft.client.renderer.RenderType import net.minecraft.network.FriendlyByteBuf import net.minecraft.resources.ResourceLocation import org.lwjgl.opengl.GL11.GL_ALWAYS +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.IGUIRenderable import ru.dbotthepony.mc.otm.client.render.IUVCoords import ru.dbotthepony.mc.otm.client.render.UVWindingOrder import ru.dbotthepony.mc.otm.client.render.color import ru.dbotthepony.mc.otm.client.render.renderTexturedRect -import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.linearInterpolation import java.util.concurrent.ConcurrentHashMap diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt index 1d0bb769f..4b45c508e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt @@ -16,6 +16,8 @@ import net.minecraftforge.client.event.ContainerScreenEvent.Render.Background import net.minecraftforge.client.event.ContainerScreenEvent.Render.Foreground import net.minecraftforge.common.MinecraftForge import org.lwjgl.opengl.GL11 +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.moveMousePosScaled diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/HoloSignScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/HoloSignScreen.kt index 219e89685..f291876b3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/HoloSignScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/HoloSignScreen.kt @@ -14,7 +14,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeRectangleButtonPan import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls import ru.dbotthepony.mc.otm.client.screen.panels.input.NetworkedStringInputPanel import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.menu.decorative.HoloSignMenu import ru.dbotthepony.mc.otm.registry.MItems diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/PainterScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/PainterScreen.kt index 1d278384c..5651c2859 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/PainterScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/PainterScreen.kt @@ -28,7 +28,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollableCanvasPanel import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.map -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.util.CreativeMenuItemComparator import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu @@ -126,8 +126,8 @@ class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : val buttons = ArrayList>() - menu.listeners.addListener { - if (frame.isRemoved) return@addListener + menu.listeners.addListener(Runnable { + if (frame.isRemoved) return@Runnable buttons.forEach { it.remove() } buttons.clear() @@ -186,7 +186,7 @@ class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : } } } - } + }) DeviceControls(this, frame, itemConfig = menu.itemConfig) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterPanelScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterPanelScreen.kt index b8cc65f16..10a39519d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterPanelScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterPanelScreen.kt @@ -21,8 +21,8 @@ import ru.dbotthepony.mc.otm.client.screen.panels.util.DiscreteScrollBarPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollBarConstants import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.asGetterSetter -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.core.math.integerDivisionDown import ru.dbotthepony.mc.otm.core.util.ItemSorter import ru.dbotthepony.mc.otm.core.util.formatMatter @@ -55,7 +55,7 @@ class MatterPanelScreen( val controls = DeviceControls(this, frame) - controls.sortingButtons(menu.settings::isAscending.asGetterSetter(), menu.settings::sorting.asGetterSetter(), ItemSorter.DEFAULT) { + controls.sortingButtons(Delegate.Of(menu.settings::isAscending), Delegate.Of(menu.settings::sorting), ItemSorter.DEFAULT) { for (v in ItemSorter.entries) { add(v, skinElement = v.icon, tooltip = v.title) } @@ -65,7 +65,7 @@ class MatterPanelScreen( LargeBooleanRectangleButtonPanel( this, frame, - prop = menu::isProvidingTasks.asGetterSetter(), + prop = Delegate.Of(menu::isProvidingTasks), iconActive = Widgets18.PLAY, iconInactive = Widgets18.PAUSE, tooltipActive = TranslatableComponent("otm.gui.matter_panel.is_providing_tasks"), diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ColorPicker.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ColorPicker.kt index da7fec976..63083b69e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ColorPicker.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ColorPicker.kt @@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.floats.FloatConsumer import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component import net.minecraft.resources.ResourceLocation +import ru.dbotthepony.kommons.math.HSVColor import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.client.CursorType import ru.dbotthepony.mc.otm.client.render.MGUIGraphics @@ -19,8 +20,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.AbstractButtonPanel import ru.dbotthepony.mc.otm.client.screen.panels.input.TextInputPanel import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.math.HSVColor -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import java.util.function.Consumer import java.util.function.Supplier import kotlin.math.roundToInt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EffectListPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EffectListPanel.kt index d682f52f7..40ae1f12d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EffectListPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EffectListPanel.kt @@ -14,7 +14,7 @@ import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.determineTooltipPosition import ru.dbotthepony.mc.otm.client.render.sprites.sprite import ru.dbotthepony.mc.otm.client.screen.panels.util.DiscreteScrollBarPanel -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.util.formatTickDuration import ru.dbotthepony.mc.otm.core.math.integerDivisionDown diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt index 002ba34d3..86dac7021 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt @@ -18,9 +18,9 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.SmallBooleanRectangleBu import ru.dbotthepony.mc.otm.client.screen.panels.button.SmallRectangleButtonPanel import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleRenderButton import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorLoaded -import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.network.DisableExopackGlowPacket import ru.dbotthepony.mc.otm.network.DisplayExopackPacket import ru.dbotthepony.mc.otm.network.EnableExopackGlowPacket @@ -57,7 +57,7 @@ private fun createExopackAppearanceWindow(screen: MatteryScreen<*>, matteryPlaye screen, frame, text = TranslatableComponent("otm.gui.exopack.toggle_visibility"), - isChecked = GetterSetter.of( + isChecked = Delegate.Of( { matteryPlayer.isExopackVisible }, @@ -78,7 +78,7 @@ private fun createExopackAppearanceWindow(screen: MatteryScreen<*>, matteryPlaye screen, frame, text = TranslatableComponent("otm.gui.exopack.toggle_glow"), - isChecked = GetterSetter.of( + isChecked = Delegate.Of( { matteryPlayer.exopackGlows }, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt index a2b34e409..37b7965c6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt @@ -13,7 +13,7 @@ import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.client.render.sprites.StretchingRectangleElement import ru.dbotthepony.mc.otm.client.screen.panels.button.AbstractButtonPanel import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor open class FramePanel( screen: S, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/Label.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/Label.kt index 39dfe7e35..312e90d56 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/Label.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/Label.kt @@ -5,7 +5,7 @@ import net.minecraft.network.chat.Component import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.core.TextComponent -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor open class Label @JvmOverloads constructor( screen: S, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/BooleanRectangleButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/BooleanRectangleButtonPanel.kt index 2ca9ba092..64f0a7217 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/BooleanRectangleButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/BooleanRectangleButtonPanel.kt @@ -3,14 +3,14 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import net.minecraft.ChatFormatting import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.value import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.render.IGUIRenderable import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.value import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback abstract class BooleanRectangleButtonPanel( @@ -20,7 +20,7 @@ abstract class BooleanRectangleButtonPanel( y: Float = 0f, width: Float, height: Float, - val prop: GetterSetter, + val prop: Delegate, var iconActive: IGUIRenderable? = null, var iconInactive: IGUIRenderable? = null, val onChange: ((newValue: Boolean) -> Unit)? = null, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/ButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/ButtonPanel.kt index ec7906a9d..d5b87d7ea 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/ButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/ButtonPanel.kt @@ -6,7 +6,7 @@ import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import java.util.function.IntConsumer open class ButtonPanel( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt index 84bf87450..7d0919e51 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt @@ -5,6 +5,8 @@ import net.minecraft.ChatFormatting import net.minecraft.network.chat.Component import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Items +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.value import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting import ru.dbotthepony.mc.otm.capability.FlowDirection @@ -24,14 +26,11 @@ import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel import ru.dbotthepony.mc.otm.config.ClientConfig -import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.asGetterSetter import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.math.RelativeSide import ru.dbotthepony.mc.otm.core.util.ItemStackSorter -import ru.dbotthepony.mc.otm.core.value import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.UpgradeSlots import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback @@ -78,7 +77,7 @@ private class PullPushButton, T : Enum>( x: Float = 0f, y: Float = 0f, enum: Class, - prop: GetterSetter, + prop: Delegate, defaultValue: T, val pullProp: BooleanInputWithFeedback, val pushProp: BooleanInputWithFeedback @@ -372,7 +371,7 @@ class DeviceControls>( alignButtons() } - fun addStorageMode(prop: GetterSetter) { + fun addStorageMode(prop: Delegate) { val mode = LargeEnumRectangleButtonPanel(screen, this, prop = prop, defaultValue = FlowDirection.BI_DIRECTIONAL, enum = FlowDirection::class.java) mode.add(FlowDirection.INPUT, Widgets18.ONLY_STORE, FlowDirection.INPUT.title) @@ -383,7 +382,7 @@ class DeviceControls>( addButton(mode) } - inline fun > sortingButtons(ascending: GetterSetter, sorting: GetterSetter, default: T, configurator: LargeEnumRectangleButtonPanel.() -> Unit): List> { + inline fun > sortingButtons(ascending: Delegate, sorting: Delegate, default: T, configurator: LargeEnumRectangleButtonPanel.() -> Unit): List> { val result = ArrayList>() LargeBooleanRectangleButtonPanel( @@ -439,7 +438,7 @@ class DeviceControls>( set(value) {} private fun makeButtons() { - buttons = sortingButtons(input.settings::isAscending.asGetterSetter(), input.settings::sorting.asGetterSetter(), ItemStackSorter.DEFAULT) { + buttons = sortingButtons(Delegate.Of(input.settings::isAscending), Delegate.Of(input.settings::sorting), ItemStackSorter.DEFAULT) { for (v in ItemStackSorter.entries) { add(v, v.icon, v.title) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxInputPanel.kt index 7d266e86b..899242293 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxInputPanel.kt @@ -1,11 +1,8 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import net.minecraft.client.gui.screens.Screen -import net.minecraft.world.entity.player.Player import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.GetterSetter -import ru.dbotthepony.mc.otm.core.value import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback open class CheckBoxInputPanel( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxLabelPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxLabelPanel.kt index 19893eb3f..394eac64d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxLabelPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxLabelPanel.kt @@ -2,9 +2,9 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.client.screen.panels.Label -import ru.dbotthepony.mc.otm.core.GetterSetter open class CheckBoxLabelPanel( screen: S, @@ -14,7 +14,7 @@ open class CheckBoxLabelPanel( y: Float = 0f, width: Float = CheckBoxPanel.REGULAR_DIMENSIONS + 120f, height: Float = CheckBoxPanel.REGULAR_DIMENSIONS, - isChecked: GetterSetter = GetterSetter.box(false) + isChecked: Delegate = Delegate.Box(false) ) : AbstractCheckBoxLabelPanel(screen, parent, x, y, width, height) { override val checkbox = CheckBoxPanel(screen, this, 0f, 0f, isChecked = isChecked) override val label = Label(screen, this, CheckBoxPanel.REGULAR_DIMENSIONS + 4f, 4f, text = text) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxPanel.kt index 7e7fa776f..bdfe883c6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/CheckBoxPanel.kt @@ -1,11 +1,11 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import net.minecraft.client.gui.screens.Screen +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.sprites.AbstractMatterySprite import ru.dbotthepony.mc.otm.client.render.WidgetLocation import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.GetterSetter open class CheckBoxPanel( screen: S, @@ -14,7 +14,7 @@ open class CheckBoxPanel( y: Float = 0f, width: Float = REGULAR_DIMENSIONS, height: Float = REGULAR_DIMENSIONS, - open val isChecked: GetterSetter = GetterSetter.box(false) + open val isChecked: Delegate = Delegate.Box(false) ) : AbstractButtonPanel(screen, parent, x, y, width, height) { open val IDLE_UNCHECKED: AbstractMatterySprite = Companion.IDLE_UNCHECKED open val IDLE_CHECKED: AbstractMatterySprite = Companion.IDLE_CHECKED diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/EnumRectangleButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/EnumRectangleButtonPanel.kt index ede8a66dd..7ac646221 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/EnumRectangleButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/EnumRectangleButtonPanel.kt @@ -4,13 +4,15 @@ import com.mojang.blaze3d.platform.InputConstants import net.minecraft.ChatFormatting import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component +import ru.dbotthepony.kommons.io.StreamCodec +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.value import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.render.IGUIRenderable import ru.dbotthepony.mc.otm.client.render.UVWindingOrder import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.core.* -import ru.dbotthepony.mc.otm.core.util.EnumValueCodec import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback import java.util.* import java.util.function.Predicate @@ -24,10 +26,10 @@ abstract class EnumRectangleButtonPanel>( width: Float, height: Float, enum: Class, - val prop: GetterSetter, + val prop: Delegate, val defaultValue: T, ) : RectangleButtonPanel(screen, parent, x, y, width, height, null) { - val enum = EnumValueCodec.searchClass(enum) + val enum = StreamCodec.Enum.searchClass(enum) private val constants: Array = enum.enumConstants private var isBuilding = true var predicate: Predicate = Predicate { true } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeBooleanRectangleButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeBooleanRectangleButtonPanel.kt index 714d701b9..86328b2ed 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeBooleanRectangleButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeBooleanRectangleButtonPanel.kt @@ -2,10 +2,10 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.client.render.IGUIRenderable import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.GetterSetter open class LargeBooleanRectangleButtonPanel( screen: S, @@ -14,7 +14,7 @@ open class LargeBooleanRectangleButtonPanel( y: Float = 0f, width: Float = SIZE, height: Float = SIZE, - prop: GetterSetter, + prop: Delegate, iconActive: IGUIRenderable? = null, iconInactive: IGUIRenderable? = null, onChange: ((newValue: Boolean) -> Unit)? = null, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeEnumRectangleButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeEnumRectangleButtonPanel.kt index d4bff231b..e11063e92 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeEnumRectangleButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeEnumRectangleButtonPanel.kt @@ -1,11 +1,9 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import net.minecraft.client.gui.screens.Screen -import ru.dbotthepony.mc.otm.client.minecraft +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.GetterSetter -import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback open class LargeEnumRectangleButtonPanel>( screen: S, @@ -15,7 +13,7 @@ open class LargeEnumRectangleButtonPanel>( width: Float = SIZE, height: Float = SIZE, enum: Class, - prop: GetterSetter, + prop: Delegate, defaultValue: T, ) : EnumRectangleButtonPanel(screen, parent, x, y, width, height, enum, prop, defaultValue) { final override val IDLE = Widgets18.BUTTON_IDLE diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeRectangleButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeRectangleButtonPanel.kt index be7a3cc60..0db554169 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeRectangleButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeRectangleButtonPanel.kt @@ -7,7 +7,7 @@ import ru.dbotthepony.mc.otm.client.render.IGUIRenderable import ru.dbotthepony.mc.otm.client.render.UVWindingOrder import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.menu.MatteryMenu open class LargeRectangleButtonPanel( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/SmallBooleanRectangleButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/SmallBooleanRectangleButtonPanel.kt index c9106179d..090a95144 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/SmallBooleanRectangleButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/SmallBooleanRectangleButtonPanel.kt @@ -1,10 +1,10 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import net.minecraft.client.gui.screens.Screen +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.client.render.sprites.AbstractMatterySprite import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.GetterSetter open class SmallBooleanRectangleButtonPanel( screen: S, @@ -13,7 +13,7 @@ open class SmallBooleanRectangleButtonPanel( y: Float = 0f, width: Float = SIZE, height: Float = SIZE, - prop: GetterSetter, + prop: Delegate, skinElementActive: AbstractMatterySprite? = null, skinElementInactive: AbstractMatterySprite? = null, onChange: ((newValue: Boolean) -> Unit)? = null, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/SmallEnumRectangleButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/SmallEnumRectangleButtonPanel.kt index 29444e7db..2dd0383ff 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/SmallEnumRectangleButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/SmallEnumRectangleButtonPanel.kt @@ -1,9 +1,9 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import net.minecraft.client.gui.screens.Screen +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.client.render.Widgets8 import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.GetterSetter open class SmallEnumRectangleButtonPanel>( screen: S, @@ -13,7 +13,7 @@ open class SmallEnumRectangleButtonPanel>( width: Float = SIZE, height: Float = SIZE, enum: Class, - prop: GetterSetter, + prop: Delegate, defaultValue: T, ) : EnumRectangleButtonPanel(screen, parent, x, y, width, height, enum, prop, defaultValue) { final override val IDLE = Widgets8.BUTTON_IDLE diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkNumberInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkNumberInputPanel.kt index 8b81f30f7..5d21db32a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkNumberInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkNumberInputPanel.kt @@ -6,6 +6,7 @@ import ru.dbotthepony.mc.otm.client.CursorType import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.core.TextComponent +import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.menu.MatteryMenu import java.math.BigDecimal import java.util.function.BooleanSupplier @@ -13,8 +14,8 @@ import java.util.function.BooleanSupplier open class NetworkNumberInputPanel @JvmOverloads constructor( screen: S, parent: EditablePanel<*>?, - val networkValue: () -> BigDecimal, - val callback: (BigDecimal) -> Unit, + val networkValue: () -> Decimal, + val callback: (Decimal) -> Unit, val isEnabled: BooleanSupplier = BooleanSupplier { true }, x: Float = 0f, y: Float = 0f, @@ -25,8 +26,8 @@ open class NetworkNumberInputPanel @JvmOverloads constructor( constructor( screen: S, parent: EditablePanel<*>?, - widget: MatteryMenu.PlayerInput, - networkValue: () -> BigDecimal, + widget: MatteryMenu.PlayerInput, + networkValue: () -> Decimal, x: Float = 0f, y: Float = 0f, width: Float = 0f, @@ -69,14 +70,14 @@ open class NetworkNumberInputPanel @JvmOverloads constructor( } if (nextUpdateFromServer < System.currentTimeMillis()) { - getOrCreateWidget().value = networkValue.invoke().toPlainString() + getOrCreateWidget().value = networkValue.invoke().toString() inputStr = getOrCreateWidget().value } else if (isEnabled.asBoolean) { if (inputStr != getOrCreateWidget().value) { inputStr = getOrCreateWidget().value try { - callback.invoke(BigDecimal(inputStr)) + callback.invoke(Decimal(inputStr)) } catch (_: Throwable) { } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NumberInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NumberInputPanel.kt index b96963ee7..d2750c805 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NumberInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NumberInputPanel.kt @@ -2,19 +2,19 @@ package ru.dbotthepony.mc.otm.client.screen.panels.input import com.mojang.blaze3d.platform.InputConstants import net.minecraft.client.gui.screens.Screen +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.client.render.Widgets import ru.dbotthepony.mc.otm.client.screen.panels.Dock import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.client.screen.panels.button.RectangleButtonPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.HeightControls -import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.math.Decimal abstract class NumberInputPanel( screen: S, parent: EditablePanel<*>, - val prop: GetterSetter, + val prop: Delegate, x: Float = 0f, y: Float = 0f, width: Float = WIDTH, @@ -129,7 +129,7 @@ abstract class NumberInputPanel( abstract class LNumberInputPanel( screen: S, parent: EditablePanel<*>, - prop: GetterSetter, + prop: Delegate, x: Float = 0f, y: Float = 0f, width: Float = WIDTH, @@ -157,7 +157,7 @@ abstract class LNumberInputPanel( open class IntInputPanel( screen: S, parent: EditablePanel<*>, - prop: GetterSetter, + prop: Delegate, x: Float = 0f, y: Float = 0f, width: Float = WIDTH, @@ -185,7 +185,7 @@ open class IntInputPanel( open class DecimalInputPanel( screen: S, parent: EditablePanel<*>, - prop: GetterSetter, + prop: Delegate, x: Float = 0f, y: Float = 0f, width: Float = WIDTH, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt index ae8dfaf87..929ce3368 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt @@ -28,7 +28,7 @@ import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.addAll import ru.dbotthepony.mc.otm.core.collect.map import ru.dbotthepony.mc.otm.core.collect.reduce -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.milliTime import java.util.function.Predicate import kotlin.math.roundToInt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/AbstractSlotPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/AbstractSlotPanel.kt index dec8c84ee..e31357af2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/AbstractSlotPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/AbstractSlotPanel.kt @@ -11,7 +11,7 @@ import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.WidgetLocation import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor abstract class AbstractSlotPanel>( screen: S, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/FilterSlotPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/FilterSlotPanel.kt index e3f67d5ea..b3ebe2cab 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/FilterSlotPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/FilterSlotPanel.kt @@ -1,14 +1,14 @@ package ru.dbotthepony.mc.otm.client.screen.panels.slot import net.minecraft.world.item.ItemStack +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.GetterSetter open class FilterSlotPanel> @JvmOverloads constructor( screen: S, parent: EditablePanel<*>?, - val slot: GetterSetter, + val slot: Delegate, x: Float = 0f, y: Float = 0f, width: Float = SIZE, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/UserFilteredSlotPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/UserFilteredSlotPanel.kt index a1a1989f5..d36d53db7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/UserFilteredSlotPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/UserFilteredSlotPanel.kt @@ -14,10 +14,12 @@ import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.playGuiClickSound import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.menu.UserFilteredSlot abstract class UserFilteredSlotPanel, out T : Slot>( @@ -122,7 +124,7 @@ abstract class UserFilteredSlotPanel, out T : Slot>( y: Float = 0f, width: Float = SIZE, height: Float = SIZE, - filter: GetterSetter + filter: Delegate ): UserFilteredSlotPanel { return object : UserFilteredSlotPanel(screen, parent, slot, x, y, width, height) { override var slotFilter: Item? by filter diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/DriveViewerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/DriveViewerScreen.kt index 95769454c..52a82e135 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/DriveViewerScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/DriveViewerScreen.kt @@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Items +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.client.render.ItemStackIcon import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.core.TranslatableComponent @@ -16,7 +17,6 @@ import ru.dbotthepony.mc.otm.client.screen.panels.slot.FilterSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel import ru.dbotthepony.mc.otm.client.screen.widget.WideProfiledPowerGaugePanel -import ru.dbotthepony.mc.otm.core.asGetterSetter import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem import ru.dbotthepony.mc.otm.menu.storage.DriveViewerMenu @@ -35,7 +35,7 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp val controls = DeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig) - controls.sortingButtons(menu.settings::isAscending.asGetterSetter(), menu.settings::sorting.asGetterSetter(), ItemStorageStackSorter.DEFAULT) { + controls.sortingButtons(Delegate.Of(menu.settings::isAscending), Delegate.Of(menu.settings::sorting), ItemStorageStackSorter.DEFAULT) { for (v in ItemStorageStackSorter.entries) { add(v, v.icon, v.title) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/ItemMonitorScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/ItemMonitorScreen.kt index 03ea70ec7..163f913d0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/ItemMonitorScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/ItemMonitorScreen.kt @@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Items +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.screen.MatteryScreen @@ -23,7 +24,6 @@ import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WideProfiledPowerGaugePanel import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.asGetterSetter import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter import ru.dbotthepony.mc.otm.menu.storage.ItemMonitorMenu import yalter.mousetweaks.api.MouseTweaksDisableWheelTweak @@ -52,7 +52,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp val controls = DeviceControls(this, frame) - controls.sortingButtons(menu.settings::ascendingSort.asGetterSetter(), menu.settings::sorting.asGetterSetter(), ItemStorageStackSorter.DEFAULT) { + controls.sortingButtons(Delegate.Of(menu.settings::ascendingSort), Delegate.Of(menu.settings::sorting), ItemStorageStackSorter.DEFAULT) { for (v in ItemStorageStackSorter.entries) { add(v, skinElement = v.icon, tooltip = v.title) } @@ -83,7 +83,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp SmallEnumRectangleButtonPanel(this, arrowLine, enum = ItemMonitorPlayerSettings.IngredientPriority::class.java, - prop = menu.settings::ingredientPriority.asGetterSetter(), + prop = Delegate.Of(menu.settings::ingredientPriority), defaultValue = ItemMonitorPlayerSettings.IngredientPriority.SYSTEM) .also { it.tooltips.add(TranslatableComponent("otm.gui.item_monitor.refill_source.desc")) @@ -104,7 +104,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp SmallEnumRectangleButtonPanel(this, resultAndButtons, y = 38f, enum = ItemMonitorPlayerSettings.ResultTarget::class.java, - prop = menu.settings::resultTarget.asGetterSetter(), + prop = Delegate.Of(menu.settings::resultTarget), defaultValue = ItemMonitorPlayerSettings.ResultTarget.MIXED) .also { it.tooltips.add(TranslatableComponent("otm.gui.item_monitor.result_target.desc")) @@ -116,7 +116,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp SmallEnumRectangleButtonPanel(this, resultAndButtons, x = 10f, y = 38f, enum = ItemMonitorPlayerSettings.Amount::class.java, - prop = menu.settings::craftingAmount.asGetterSetter(), + prop = Delegate.Of(menu.settings::craftingAmount), defaultValue = ItemMonitorPlayerSettings.Amount.STACK) .also { it.tooltips.add(TranslatableComponent("otm.gui.item_monitor.amount.desc")) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt index 3bac104b9..387ef43af 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt @@ -31,7 +31,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.slot.EquipmentBatterySlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.DraggableCanvasPanel import ru.dbotthepony.mc.otm.client.screen.widget.WideProfiledPowerGaugePanel import ru.dbotthepony.mc.otm.config.MachinesConfig -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/FluidGaugePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/FluidGaugePanel.kt index cccd7e3ac..0a3f10eee 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/FluidGaugePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/FluidGaugePanel.kt @@ -22,7 +22,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.isNotEmpty -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.linearInterpolation import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.util.formatFluidLevel diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/MatterGaugePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/MatterGaugePanel.kt index b4ce06a6e..cd05ee603 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/MatterGaugePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/MatterGaugePanel.kt @@ -10,6 +10,7 @@ import net.minecraft.client.gui.screens.Screen import net.minecraft.client.renderer.GameRenderer import net.minecraft.network.chat.Component import org.lwjgl.opengl.GL11 +import ru.dbotthepony.kommons.util.value import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.ShiftPressedCond diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/PowerGaugePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/PowerGaugePanel.kt index 537b71f20..0d5b6546b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/PowerGaugePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/widget/PowerGaugePanel.kt @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.ints.IntArrayList import net.minecraft.ChatFormatting import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component +import ru.dbotthepony.kommons.util.value import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.ShiftPressedCond diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/JadeCompatData.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/JadeCompatData.kt index 7678283fb..94e4ca7a9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/JadeCompatData.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/JadeCompatData.kt @@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.compat.jade import net.minecraft.resources.ResourceLocation import ru.dbotthepony.mc.otm.OverdriveThatMatters.loc -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor object JadeUids { val MATTERY_ENERGY: ResourceLocation = loc("mattery_energy") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterBottlerProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterBottlerProvider.kt index c44d42c25..d43f7827f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterBottlerProvider.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterBottlerProvider.kt @@ -7,7 +7,7 @@ import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity import ru.dbotthepony.mc.otm.compat.jade.JadeTagKeys import ru.dbotthepony.mc.otm.compat.jade.JadeUids import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import snownee.jade.api.BlockAccessor import snownee.jade.api.IBlockComponentProvider import snownee.jade.api.IServerDataProvider diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterReconstructorProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterReconstructorProvider.kt index 456e555f0..0d4d3cf2d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterReconstructorProvider.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterReconstructorProvider.kt @@ -6,7 +6,7 @@ import ru.dbotthepony.mc.otm.block.entity.matter.MatterReconstructorBlockEntity import ru.dbotthepony.mc.otm.compat.jade.JadeTagKeys import ru.dbotthepony.mc.otm.compat.jade.JadeUids import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import snownee.jade.api.BlockAccessor import snownee.jade.api.IBlockComponentProvider import snownee.jade.api.IServerDataProvider diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterStorageProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterStorageProvider.kt index e6f7ddd03..273f4f8f0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterStorageProvider.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatterStorageProvider.kt @@ -12,7 +12,7 @@ import ru.dbotthepony.mc.otm.compat.jade.JadeUids import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.core.math.Decimal -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.getDecimal import ru.dbotthepony.mc.otm.core.math.putDecimal import ru.dbotthepony.mc.otm.core.util.formatMatter diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatteryEnergyProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatteryEnergyProvider.kt index 3c0855d34..1ca7fe8ae 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatteryEnergyProvider.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatteryEnergyProvider.kt @@ -12,7 +12,7 @@ import ru.dbotthepony.mc.otm.compat.jade.JadeUids import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.core.math.Decimal -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.getDecimal import ru.dbotthepony.mc.otm.core.math.putDecimal import ru.dbotthepony.mc.otm.core.util.formatPower diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatteryWorkerProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatteryWorkerProvider.kt index bda41684e..be7310055 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatteryWorkerProvider.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jade/providers/MatteryWorkerProvider.kt @@ -7,7 +7,7 @@ import ru.dbotthepony.mc.otm.block.entity.ItemJob import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity import ru.dbotthepony.mc.otm.compat.jade.JadeTagKeys import ru.dbotthepony.mc.otm.compat.jade.JadeUids -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.nbt.getCompoundList import ru.dbotthepony.mc.otm.core.nbt.getItemStack import ru.dbotthepony.mc.otm.core.nbt.set diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/MicrowaveRecipeCategory.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/MicrowaveRecipeCategory.kt index dd93d7796..74e5f6872 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/MicrowaveRecipeCategory.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/MicrowaveRecipeCategory.kt @@ -18,7 +18,7 @@ import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.recipe.MicrowaveRecipe diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/PlatePressRecipeCategory.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/PlatePressRecipeCategory.kt index 6d8dddd76..5b6759e34 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/PlatePressRecipeCategory.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/PlatePressRecipeCategory.kt @@ -18,7 +18,7 @@ import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/vanilla/MatteryChestMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/vanilla/MatteryChestMenu.kt index 6ed91b59f..446cb3fb3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/vanilla/MatteryChestMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/vanilla/MatteryChestMenu.kt @@ -11,6 +11,7 @@ import net.minecraft.world.inventory.MenuType import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent import net.minecraftforge.registries.DeferredRegister +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.core.getValue import ru.dbotthepony.mc.otm.menu.MatteryMenu diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/AbstractConfig.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/AbstractConfig.kt index 24b64492f..d56270c19 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/AbstractConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/AbstractConfig.kt @@ -3,8 +3,9 @@ package ru.dbotthepony.mc.otm.config import net.minecraftforge.common.ForgeConfigSpec import net.minecraftforge.fml.ModLoadingContext import net.minecraftforge.fml.config.ModConfig +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.OverdriveThatMatters -import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.getValue import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.defineDecimal @@ -59,10 +60,10 @@ abstract class AbstractConfig(private val configName: String, private val type: val obj = object : WorkerBalanceValues { override val energyCapacity: Decimal by builder.defineDecimal("ENERGY_CAPACITY", energyStorage, minimum = Decimal.ONE) override val energyThroughput: Decimal by builder.defineDecimal("ENERGY_THROUGHPUT", energyThroughput, minimum = Decimal.ONE) - override val energyConsumption: Decimal by (if (energyConsumption == null) GetterSetter.box(Decimal.ZERO) else builder.defineDecimal("ENERGY_CONSUMPTION", energyConsumption, minimum = Decimal.ONE)) - override val matterCapacity: Decimal by (if (matterCapacity == null) GetterSetter.box(Decimal.ZERO) else builder.defineDecimal("MATTER_CAPACITY", matterCapacity, minimum = Decimal.ONE)) - override val workTimeMultiplier: Double by (if (workTimeMultiplier == null) GetterSetter.box(1.0) else builder.defineInRange("WORK_TIME_MULTIPLIER", workTimeMultiplier, 0.0)) - override val maxExperienceStored: Double by (if (maxExperience == null) GetterSetter.box(Double.POSITIVE_INFINITY) else builder.defineInRange("MAX_EXPERIENCE_STORED", maxExperience, 0.0)) + override val energyConsumption: Decimal by (if (energyConsumption == null) Delegate.Box(Decimal.ZERO) else builder.defineDecimal("ENERGY_CONSUMPTION", energyConsumption, minimum = Decimal.ONE)) + override val matterCapacity: Decimal by (if (matterCapacity == null) Delegate.Box(Decimal.ZERO) else builder.defineDecimal("MATTER_CAPACITY", matterCapacity, minimum = Decimal.ONE)) + override val workTimeMultiplier: Double by (if (workTimeMultiplier == null) Delegate.Box(1.0) else builder.defineInRange("WORK_TIME_MULTIPLIER", workTimeMultiplier, 0.0)) + override val maxExperienceStored: Double by (if (maxExperience == null) Delegate.Box(Double.POSITIVE_INFINITY) else builder.defineInRange("MAX_EXPERIENCE_STORED", maxExperience, 0.0)) } configurator.invoke(builder) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/AndroidConfig.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/AndroidConfig.kt index 09bcdb1c5..f49f231d9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/AndroidConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/AndroidConfig.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.mc.otm.config +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.defineDecimal diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/CablesConfig.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/CablesConfig.kt index d9b13b56d..c63e91c44 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/CablesConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/CablesConfig.kt @@ -1,5 +1,7 @@ package ru.dbotthepony.mc.otm.config +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.defineDecimal diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/ExopackConfig.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/ExopackConfig.kt index ecc938e42..afe73a16a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/ExopackConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/ExopackConfig.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.mc.otm.config +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.defineDecimal diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/ItemsConfig.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/ItemsConfig.kt index 7d11124b2..83bf3dfd7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/ItemsConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/ItemsConfig.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.mc.otm.config +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.defineDecimal import ru.dbotthepony.mc.otm.registry.MNames diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt index 4f08725d3..139e483c0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.mc.otm.config +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.defineDecimal import ru.dbotthepony.mc.otm.registry.MNames diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/ObservedConfigValue.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/ObservedConfigValue.kt index a2a97bfa9..ca69d1fba 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/ObservedConfigValue.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/ObservedConfigValue.kt @@ -2,13 +2,9 @@ package ru.dbotthepony.mc.otm.config import net.minecraftforge.common.ForgeConfigSpec.ConfigValue import org.apache.logging.log4j.LogManager -import ru.dbotthepony.mc.otm.core.GetterSetter -import java.util.function.Consumer -import java.util.function.Supplier -import kotlin.properties.ReadWriteProperty -import kotlin.reflect.KProperty +import ru.dbotthepony.kommons.util.Delegate -abstract class ObservedConfigValue(val parent: ConfigValue) : GetterSetter { +abstract class ObservedConfigValue(val parent: ConfigValue) : Delegate { var rawValue: String by parent private var observedValue: String? = null private var cachedValue: V? = null @@ -44,10 +40,6 @@ abstract class ObservedConfigValue(val parent: ConfigValue) : G return cachedValue ?: throw ConcurrentModificationException() } - override fun getValue(thisRef: Any?, property: KProperty<*>): V { - return get() - } - override fun accept(value: V) { if (cachedValue == null || rawValue != observedValue) { cachedValue = fromString(rawValue) @@ -65,10 +57,6 @@ abstract class ObservedConfigValue(val parent: ConfigValue) : G } } - override fun setValue(thisRef: Any?, property: KProperty<*>, value: V) { - accept(value) - } - companion object { private val LOGGER = LogManager.getLogger() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/MatteryContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/MatteryContainer.kt index 688d803cd..ca3f6a276 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/MatteryContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/MatteryContainer.kt @@ -19,6 +19,9 @@ import net.minecraft.world.item.Item import net.minecraft.world.item.Items import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.registries.ForgeRegistries +import ru.dbotthepony.kommons.collect.ListenableMap +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.io.VarIntValueCodec import ru.dbotthepony.mc.otm.container.util.IContainerSlot import ru.dbotthepony.mc.otm.core.addSorted import ru.dbotthepony.mc.otm.core.collect.any @@ -31,10 +34,6 @@ import ru.dbotthepony.mc.otm.core.nbt.map import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.util.ItemValueCodec -import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer -import ru.dbotthepony.mc.otm.network.synchronizer.IField -import java.lang.ref.WeakReference import java.util.* import java.util.function.Consumer import java.util.function.Predicate @@ -77,7 +76,7 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I private val trackedSlots: Array = Array(size) { ItemStack.EMPTY } private val filters: Array = arrayOfNulls(size) - private var filterSynchronizer: WeakReference>>? = null + private var filterSynchronizer: DelegateSyncher.MapSlot? = null var changeset = 0 private set @@ -108,35 +107,44 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I fun clearSlotFilters() { Arrays.fill(filters, null) - filterSynchronizer?.get()?.value?.clear() + filterSynchronizer?.delegate?.clear() } fun removeFilterSynchronizer() { - filterSynchronizer?.get()?.remove() + filterSynchronizer?.remove() filterSynchronizer = null } - fun addFilterSynchronizer(synchronizer: FieldSynchronizer): IField> { - check(filterSynchronizer?.get() == null) { "Already has filter synchronizer" } + fun addFilterSynchronizer(synchronizer: DelegateSyncher): DelegateSyncher.MapSlot { + check(filterSynchronizer?.delegate == null) { "Already has filter synchronizer" } - val field = synchronizer.Map( + val field = synchronizer.MapSlot( + ListenableMap(Int2ObjectOpenHashMap()), keyCodec = VarIntValueCodec, valueCodec = ItemValueCodec, - backingMap = Int2ObjectOpenHashMap(), - callback = { - for (change in it) { - change.map({ k, v -> filters[k] = v }, { k -> filters[k] = null }, { Arrays.fill(filters, null) }) - } - } ) for ((i, filter) in filters.withIndex()) { if (filter != null) { - field.value[i] = filter + field.delegate[i] = filter } } - filterSynchronizer = WeakReference(field) + field.addListener(object : ListenableMap.MapListener { + override fun onClear() { + Arrays.fill(filters, null) + } + + override fun onValueAdded(key: Int, value: Item) { + filters[key] = value + } + + override fun onValueRemoved(key: Int, value: Item) { + filters[key] = null + } + }) + + filterSynchronizer = field return field } @@ -144,11 +152,11 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I if (filters[slot] !== filter) { filters[slot] = filter - filterSynchronizer?.get()?.let { + filterSynchronizer?.delegate?.let { if (filter == null) { - it.value.remove(slot) + it.remove(slot) } else { - it.value[slot] = filter + it[slot] = filter } } } @@ -183,7 +191,7 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I } tag.map("filters") { it: ListTag -> - val map = filterSynchronizer?.get() + val map = filterSynchronizer?.delegate for (i in 0 until it.size.coerceAtMost(size)) { val nbt = it[i] as CompoundTag @@ -191,7 +199,7 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I filters[index] = ForgeRegistries.ITEMS.getValue(ResourceLocation.tryParse(nbt.getString("filter")) ?: continue) if (filters[index] != null) { - map?.value?.put(index, filters[index]!!) + map?.put(index, filters[index]!!) } } } @@ -233,7 +241,7 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I nonEmptyFlags.clear() nonEmptyIndices = IntArrayList() - filterSynchronizer?.get()?.value?.clear() + filterSynchronizer?.delegate?.clear() when (tag) { is CompoundTag -> deserializeNBT(tag) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/util/Iterators.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/util/Iterators.kt index e2cb1ed31..95c58087e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/util/Iterators.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/util/Iterators.kt @@ -4,11 +4,10 @@ import net.minecraft.world.Container import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Items +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.container.IMatteryContainer -import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.container.set -import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.collect.filter import ru.dbotthepony.mc.otm.core.collect.map import ru.dbotthepony.mc.otm.core.isNotEmpty @@ -17,7 +16,7 @@ import ru.dbotthepony.mc.otm.core.isNotEmpty * While this somewhat similar to [net.minecraft.world.inventory.Slot], this slot is not meant * for Player interaction. */ -interface IContainerSlot : GetterSetter { +interface IContainerSlot : Delegate { val slot: Int val container: Container diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt index f5ee5effd..e75359b92 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt @@ -41,9 +41,18 @@ import net.minecraftforge.items.IItemHandler import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistry import net.minecraftforge.registries.IForgeRegistry +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.io.StreamCodec +import ru.dbotthepony.kommons.util.DelegateGetter +import ru.dbotthepony.kommons.util.DelegateSetter +import ru.dbotthepony.kommons.util.ListenableDelegate import ru.dbotthepony.mc.otm.core.math.BlockRotation import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom +import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Vector +import ru.dbotthepony.mc.otm.core.math.readDecimal +import ru.dbotthepony.mc.otm.core.math.writeDecimal +import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec import ru.dbotthepony.mc.otm.core.util.readInt import ru.dbotthepony.mc.otm.core.util.readVarIntLE import ru.dbotthepony.mc.otm.core.util.writeInt @@ -506,3 +515,4 @@ fun lazy2(a: () -> A, b: A.() -> B): Supplier { val first = lazy(a) return Supplier { b.invoke(first.value) } } + diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt deleted file mode 100644 index a0bac0048..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt +++ /dev/null @@ -1,148 +0,0 @@ -package ru.dbotthepony.mc.otm.core - -import java.util.function.Consumer -import java.util.function.Supplier -import kotlin.properties.ReadWriteProperty -import kotlin.reflect.KMutableProperty0 -import kotlin.reflect.KProperty - -inline var GetterSetter.value: V - get() = get() - set(value) { accept(value) } - -interface GetterSetter : Supplier, Consumer, ReadWriteProperty { - override fun setValue(thisRef: Any?, property: KProperty<*>, value: V) { - accept(value) - } - - override fun getValue(thisRef: Any?, property: KProperty<*>): V { - return get() - } - - operator fun invoke(): V { - return get() - } - - operator fun invoke(value: V) { - accept(value) - } - - fun asGetterOnly(): GetterSetter { - val self = this - - return object : GetterSetter { - override fun get(): V { - return self.get() - } - - override fun accept(t: V) { - } - } - } - - fun watch(watch: (old: V, new: V) -> Unit): GetterSetter { - val self = this - - return object : GetterSetter by self { - override fun accept(t: V) { - val old = get() - self.accept(t) - watch.invoke(old, t) - } - } - } - - companion object { - fun of(getter: Supplier, setter: Consumer): GetterSetter { - return object : GetterSetter { - override fun get(): V { - return getter.get() - } - - override fun accept(t: V) { - setter.accept(t) - } - } - } - - fun of(getter: () -> V, setter: (V) -> Unit): GetterSetter { - return object : GetterSetter { - override fun get(): V { - return getter.invoke() - } - - override fun accept(t: V) { - setter.invoke(t) - } - } - } - - fun of(property: KMutableProperty0): GetterSetter { - return object : GetterSetter { - override fun get(): V { - return property.get() - } - - override fun accept(t: V) { - property.set(t) - } - } - } - - fun box(value: V): SentientGetterSetter { - return object : SentientGetterSetter { - private val subs = ISubscriptable.Impl() - - override fun addListener(listener: Consumer): ISubscriptable.L { - return subs.addListener(listener) - } - - private var value = value - - override fun get(): V { - return value - } - - override fun accept(t: V) { - this.value = t - subs.accept(t) - } - } - } - } -} - -interface SentientGetterSetter : GetterSetter, ISubscriptable { - override fun watch(watch: (old: V, new: V) -> Unit): SentientGetterSetter { - val self = this - - return object : SentientGetterSetter by self { - override fun accept(t: V) { - val old = get() - self.accept(t) - watch.invoke(old, t) - } - } - } - -} - -operator fun Supplier.getValue(thisRef: Any?, property: KProperty<*>): T { - return get() -} - -operator fun Consumer.setValue(thisRef: Any?, property: KProperty<*>, value: T) { - accept(value) -} - -fun KMutableProperty0.asGetterSetter(watch: ((old: V, new: V) -> Unit)? = null): GetterSetter { - return GetterSetter.of(this).let { - if (watch != null) { - it.watch(watch) - } else { - it - } - } -} - -fun KMutableProperty0.asGetterOnly() = GetterSetter.of(Supplier { this.get() }, Consumer { /* do nothing */ }) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/ISubscripable.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/ISubscripable.kt deleted file mode 100644 index 75f487e45..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/ISubscripable.kt +++ /dev/null @@ -1,300 +0,0 @@ -package ru.dbotthepony.mc.otm.core - -import it.unimi.dsi.fastutil.booleans.BooleanConsumer -import it.unimi.dsi.fastutil.floats.FloatConsumer -import it.unimi.dsi.fastutil.objects.ReferenceArraySet -import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet -import java.util.function.Consumer -import java.util.function.DoubleConsumer -import java.util.function.IntConsumer -import java.util.function.LongConsumer - -interface ISubscriptable { - /** - * Listener token, allows to remove listener from subscriber list - */ - fun interface L { - /** - * Removes this listener - */ - fun remove() - } - - fun addListener(listener: Consumer): L - - class Impl : ISubscriptable, Consumer { - private inner class L(val callback: Consumer) : ISubscriptable.L { - private var isRemoved = false - - init { - subscribers.add(this) - } - - override fun remove() { - if (!isRemoved) { - isRemoved = true - queue.add(this) - } - } - } - - private val subscribers = ReferenceLinkedOpenHashSet(0) - private val queue = ReferenceArraySet(0) - - override fun addListener(listener: Consumer): ISubscriptable.L { - return L(listener) - } - - override fun accept(t: V) { - queue.forEach { subscribers.remove(it) } - queue.clear() - subscribers.forEach { it.callback.accept(t) } - } - } - - companion object : ISubscriptable, L { - @Suppress("unchecked_cast") - fun empty(): ISubscriptable { - return this as ISubscriptable - } - - override fun remove() {} - - override fun addListener(listener: Consumer): L { - return this - } - } -} - -interface IUnitSubscripable : ISubscriptable { - fun addListener(listener: Runnable): ISubscriptable.L - - override fun addListener(listener: Consumer): ISubscriptable.L { - return addListener(Runnable { listener.accept(Unit) }) - } - - class Impl : IUnitSubscripable, Runnable { - private inner class L(val callback: Runnable) : ISubscriptable.L { - private var isRemoved = false - - init { - subscribers.add(this) - } - - override fun remove() { - if (!isRemoved) { - isRemoved = true - queue.add(this) - } - } - } - - private val subscribers = ReferenceLinkedOpenHashSet(0) - private val queue = ReferenceArraySet(0) - - override fun addListener(listener: Runnable): ISubscriptable.L { - return L(listener) - } - - override fun run() { - queue.forEach { subscribers.remove(it) } - queue.clear() - subscribers.forEach { it.callback.run() } - } - } -} - -interface IFloatSubcripable : ISubscriptable { - @Deprecated("Use type specific listener") - override fun addListener(listener: Consumer): ISubscriptable.L { - return addListener(listener::accept) - } - - fun addListener(listener: FloatConsumer): ISubscriptable.L - - class Impl : IFloatSubcripable, Consumer, FloatConsumer { - private inner class L(val callback: FloatConsumer) : ISubscriptable.L { - private var isRemoved = false - - init { - subscribers.add(this) - } - - override fun remove() { - if (!isRemoved) { - isRemoved = true - queue.add(this) - } - } - } - - private val subscribers = ReferenceLinkedOpenHashSet(0) - private val queue = ReferenceArraySet(0) - - override fun addListener(listener: FloatConsumer): ISubscriptable.L { - return L(listener) - } - - override fun accept(t: Float) { - queue.forEach { subscribers.remove(it) } - queue.clear() - subscribers.forEach { it.callback.accept(t) } - } - } -} - -interface IDoubleSubcripable : ISubscriptable { - @Deprecated("Use type specific listener") - override fun addListener(listener: Consumer): ISubscriptable.L { - return addListener(DoubleConsumer { listener.accept(it) }) - } - - fun addListener(listener: DoubleConsumer): ISubscriptable.L - - class Impl : IDoubleSubcripable, Consumer, DoubleConsumer { - private inner class L(val callback: DoubleConsumer) : ISubscriptable.L { - private var isRemoved = false - - init { - subscribers.add(this) - } - - override fun remove() { - if (!isRemoved) { - isRemoved = true - queue.add(this) - } - } - } - - private val subscribers = ReferenceLinkedOpenHashSet(0) - private val queue = ReferenceArraySet(0) - - override fun addListener(listener: DoubleConsumer): ISubscriptable.L { - return L(listener) - } - - override fun accept(t: Double) { - queue.forEach { subscribers.remove(it) } - queue.clear() - subscribers.forEach { it.callback.accept(t) } - } - } -} - -interface IIntSubcripable : ISubscriptable { - @Deprecated("Use type specific listener") - override fun addListener(listener: Consumer): ISubscriptable.L { - return addListener(IntConsumer { listener.accept(it) }) - } - - fun addListener(listener: IntConsumer): ISubscriptable.L - - class Impl : IIntSubcripable, Consumer, IntConsumer { - private inner class L(val callback: IntConsumer) : ISubscriptable.L { - private var isRemoved = false - - init { - subscribers.add(this) - } - - override fun remove() { - if (!isRemoved) { - isRemoved = true - queue.add(this) - } - } - } - - private val subscribers = ReferenceLinkedOpenHashSet(0) - private val queue = ReferenceArraySet(0) - - override fun addListener(listener: IntConsumer): ISubscriptable.L { - return L(listener) - } - - override fun accept(t: Int) { - queue.forEach { subscribers.remove(it) } - queue.clear() - subscribers.forEach { it.callback.accept(t) } - } - } -} - -interface ILongSubcripable : ISubscriptable { - @Deprecated("Use type specific listener") - override fun addListener(listener: Consumer): ISubscriptable.L { - return addListener(LongConsumer { listener.accept(it) }) - } - - fun addListener(listener: LongConsumer): ISubscriptable.L - - class Impl : ILongSubcripable, Consumer, LongConsumer { - private inner class L(val callback: LongConsumer) : ISubscriptable.L { - private var isRemoved = false - - init { - subscribers.add(this) - } - - override fun remove() { - if (!isRemoved) { - isRemoved = true - queue.add(this) - } - } - } - - private val subscribers = ReferenceLinkedOpenHashSet(0) - private val queue = ReferenceArraySet(0) - - override fun addListener(listener: LongConsumer): ISubscriptable.L { - return L(listener) - } - - override fun accept(t: Long) { - queue.forEach { subscribers.remove(it) } - queue.clear() - subscribers.forEach { it.callback.accept(t) } - } - } -} - -interface IBooleanSubscriptable : ISubscriptable { - @Deprecated("Use type specific listener") - override fun addListener(listener: Consumer): ISubscriptable.L { - return addListener(listener::accept) - } - - fun addListener(listener: BooleanConsumer): ISubscriptable.L - - class Impl : IBooleanSubscriptable, Consumer, BooleanConsumer { - private inner class L(val callback: BooleanConsumer) : ISubscriptable.L { - private var isRemoved = false - - init { - subscribers.add(this) - } - - override fun remove() { - if (!isRemoved) { - isRemoved = true - queue.add(this) - } - } - } - - private val subscribers = ReferenceLinkedOpenHashSet(0) - private val queue = ReferenceArraySet(0) - - override fun addListener(listener: BooleanConsumer): ISubscriptable.L { - return L(listener) - } - - override fun accept(t: Boolean) { - queue.forEach { subscribers.remove(it) } - queue.clear() - subscribers.forEach { it.callback.accept(t) } - } - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/math/Colors.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/math/Colors.kt index 9c57692b1..1f5145e34 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/math/Colors.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/math/Colors.kt @@ -2,389 +2,24 @@ package ru.dbotthepony.mc.otm.core.math import com.mojang.serialization.Codec import com.mojang.serialization.codecs.RecordCodecBuilder -import it.unimi.dsi.fastutil.chars.CharAVLTreeSet import net.minecraft.ChatFormatting -import kotlin.math.roundToInt +import ru.dbotthepony.kommons.math.RGBAColor -class HSVColor(hue: Float, saturation: Float, value: Float) : Comparable { - val hue = (hue % 360f).let { if (it < 0f) it + 360f else it } - val saturation = saturation.coerceIn(0f, 1f) - val value = value.coerceIn(0f, 1f) - - override fun equals(other: Any?): Boolean { - return other === this || other is HSVColor && other.hue == hue && other.saturation == saturation && other.value == value - } - - override fun hashCode(): Int { - return hue.hashCode() + saturation.hashCode() * 31 + value.hashCode() * 31 * 31 - } - - fun copy(hue: Float = this.hue, saturation: Float = this.saturation, value: Float = this.value): HSVColor { - return HSVColor(hue, saturation, value) - } - - operator fun component1() = hue - operator fun component2() = saturation - operator fun component3() = value - - fun toRGBA(alpha: Float = 1f): RGBAColor { - val valueMin = (1f - saturation) * value - val delta = (value - valueMin) * (hue % 60f) / 60f - val valueInc = valueMin + delta - val valueDec = value - delta - - return when ((hue / 60f).toInt()) { - 0 -> RGBAColor(value, valueInc, valueMin, alpha) - 1 -> RGBAColor(valueDec, value, valueMin, alpha) - 2 -> RGBAColor(valueMin, value, valueInc, alpha) - 3 -> RGBAColor(valueMin, valueDec, value, alpha) - 4 -> RGBAColor(valueInc, valueMin, value, alpha) - 5 -> RGBAColor(value, valueMin, valueDec, alpha) - else -> throw IllegalStateException("whut") - } - } - - override fun compareTo(other: HSVColor): Int { - return comparator.compare(this, other) - } - - companion object { - @JvmField val WHITE = HSVColor(0f, 1f, 1f) - - private val comparator = Comparator - .comparing(HSVColor::hue) - .thenComparing(HSVColor::saturation) - .thenComparing(HSVColor::value) - } +@JvmField +val RGBAColorDFUCodec: Codec = RecordCodecBuilder.create { + it.group( + Codec.floatRange(0f, 1f).fieldOf("red").forGetter(RGBAColor::red), + Codec.floatRange(0f, 1f).fieldOf("green").forGetter(RGBAColor::green), + Codec.floatRange(0f, 1f).fieldOf("blue").forGetter(RGBAColor::blue), + Codec.floatRange(0f, 1f).optionalFieldOf("alpha", 1f).forGetter(RGBAColor::alpha), + ).apply(it, ::RGBAColor) } -private fun hex(value: Int): String { - require(value in 0 .. 255) - val v = value.toString(16) - - if (v.length == 1) - return "0$v" - else - return v -} - -class RGBAColor(red: Float, green: Float, blue: Float, alpha: Float = 1f) : Comparable { - constructor(r: Int, g: Int, b: Int) : this((r / 255f), (g / 255f), (b / 255f), 1f) - constructor(r: Int, g: Int, b: Int, a: Int) : this((r / 255f), (g / 255f), (b / 255f), (a / 255f)) - constructor(r: Int, g: Int, b: Int, a: Float) : this((r / 255f), (g / 255f), (b / 255f), a) - - val red = red.coerceIn(0f, 1f) - val green = green.coerceIn(0f, 1f) - val blue = blue.coerceIn(0f, 1f) - val alpha = alpha.coerceIn(0f, 1f) - - val redInt get() = (red * 255f).roundToInt() - val greenInt get() = (green * 255f).roundToInt() - val blueInt get() = (blue * 255f).roundToInt() - val alphaInt get() = (alpha * 255f).roundToInt() - - fun toRGBA(): Int { - return (redInt shl 24) or (greenInt shl 16) or (blueInt shl 8) or alphaInt - } - - fun toARGB(): Int { - return (alphaInt shl 24) or (redInt shl 16) or (greenInt shl 8) or blueInt - } - - fun toBGRA(): Int { - return (blueInt shl 24) or (greenInt shl 16) or (redInt shl 8) or alphaInt - } - - val isFullyTransparent get() = alpha <= 0f - val isWhite: Boolean get() = red >= 1f && green >= 1f && blue >= 1f && alpha >= 1f - - fun canRepresentHue(): Boolean { - val min = red.coerceAtMost(green).coerceAtMost(blue) - val max = red.coerceAtLeast(green).coerceAtLeast(blue) - return min != max - } - - fun hue(ifNoHue: Float = 0f): Float { - val min = red.coerceAtMost(green).coerceAtMost(blue) - val max = red.coerceAtLeast(green).coerceAtLeast(blue) - - if (min == max) { - return ifNoHue - } - - val diff = max - min - - return if (max == red && green >= blue) { - 60f * (green - blue) / diff - } else if (max == red) { - 60f * (green - blue) / diff + 360f - } else if (max == green) { - 60f * (blue - red) / diff + 120f - } else if (max == blue) { - 60f * (red - green) / diff + 240f - } else { - throw IllegalStateException("Whut $red $green $blue ($min / $max)") - } - } - - fun toHSV(): HSVColor { - val min = red.coerceAtMost(green).coerceAtMost(blue) - val max = red.coerceAtLeast(green).coerceAtLeast(blue) - - if (min == max) { - return HSVColor(0f, if (max == 0f) 0f else 1f - min / max, max) - } - - val diff = max - min - - val hue = if (max == red && green >= blue) { - 60f * (green - blue) / diff - } else if (max == red) { - 60f * (green - blue) / diff + 360f - } else if (max == green) { - 60f * (blue - red) / diff + 120f - } else if (max == blue) { - 60f * (red - green) / diff + 240f - } else { - throw IllegalStateException("Whut $red $green $blue ($min / $max)") - } - - return HSVColor(hue, 1f - min / max, max) - } - - fun toHexStringRGB(): String { - return "#${hex(redInt)}${hex(greenInt)}${hex(blueInt)}" - } - - fun toHexStringRGBA(): String { - return "#${hex(redInt)}${hex(greenInt)}${hex(blueInt)}${hex(alphaInt)}" - } - - fun toHexStringARGB(): String { - return "#${hex(alphaInt)}${hex(redInt)}${hex(greenInt)}${hex(blueInt)}" - } - - override fun toString(): String { - return "RGBAColor[$red $green $blue $alpha]" - } - - operator fun component1() = red - operator fun component2() = green - operator fun component3() = blue - operator fun component4() = alpha - - fun toIntInv(): Int { - return (blueInt shl 16) or (greenInt shl 8) or redInt - } - - fun toRGB(): Int { - return (redInt shl 16) or (greenInt shl 8) or blueInt - } - - fun copy(red: Float = this.red, green: Float = this.green, blue: Float = this.blue, alpha: Float = this.alpha): RGBAColor { - return RGBAColor(red, green, blue, alpha) - } - - override fun compareTo(other: RGBAColor): Int { - if (canRepresentHue() && other.canRepresentHue()) - return hue().compareTo(other.hue()).let { - if (it != 0) - it - else - toHSV().compareTo(other.toHSV()) - } - - return comparator.compare(this, other) - } - - override fun equals(other: Any?): Boolean { - return other === this || other is RGBAColor && comparator.compare(this, other) == 0 - } - - override fun hashCode(): Int { - return red.hashCode() + green.hashCode() * 31 + blue.hashCode() * 31 * 31 + alpha.hashCode() * 31 * 31 * 31 - } - - fun linearInterpolation(t: Float, other: RGBAColor, interpolateAlpha: Boolean = true): RGBAColor { - return RGBAColor( - linearInterpolation(t, red, other.red), - linearInterpolation(t, green, other.green), - linearInterpolation(t, blue, other.blue), - if (interpolateAlpha) linearInterpolation(t, alpha, other.alpha) else alpha, - ) - } - - operator fun times(other: RGBAColor): RGBAColor { - if (isWhite) - return other - else if (other.isWhite) - return this - - return RGBAColor(red * other.red, green * other.green, blue * other.blue, alpha * other.alpha) - } - - @Suppress("unused") - companion object { - private val comparator = Comparator - .comparing(RGBAColor::red) - .thenComparing(RGBAColor::green) - .thenComparing(RGBAColor::blue) - .thenComparing(RGBAColor::alpha) - - @JvmField val TRANSPARENT_BLACK = RGBAColor(0f, 0f, 0f, 0f) - @JvmField val TRANSPARENT_WHITE = RGBAColor(1f, 1f, 1f, 0f) - - @JvmField val BLACK = RGBAColor(0f, 0f, 0f) - @JvmField val WHITE = RGBAColor(1f, 1f, 1f) - @JvmField val RED = RGBAColor(1f, 0f, 0f) - @JvmField val GREEN = RGBAColor(0f, 1f, 0f) - @JvmField val LIGHT_GREEN = RGBAColor(136, 255, 124) - @JvmField val SLATE_GRAY = RGBAColor(64, 64, 64) - @JvmField val GRAY = rgb(0x2C2C2CL) - @JvmField val LIGHT_GRAY = rgb(0x7F7F7FL) - @JvmField val HEADING_TEXT = rgb(0x404040L) - - @JvmField val DARK_BLUE = rgb(ChatFormatting.DARK_BLUE.color!!) - @JvmField val DARK_GREEN = rgb(ChatFormatting.DARK_GREEN.color!!) - @JvmField val DARK_AQUA = rgb(ChatFormatting.DARK_AQUA.color!!) - @JvmField val DARK_RED = rgb(ChatFormatting.DARK_RED.color!!) - @JvmField val DARK_PURPLE = rgb(ChatFormatting.DARK_PURPLE.color!!) - @JvmField val GOLD = rgb(ChatFormatting.GOLD.color!!) - @JvmField val DARK_GRAY = rgb(ChatFormatting.DARK_GRAY.color!!) - @JvmField val BLUE = rgb(ChatFormatting.BLUE.color!!) - @JvmField val AQUA = rgb(ChatFormatting.AQUA.color!!) - @JvmField val LIGHT_PURPLE = rgb(ChatFormatting.LIGHT_PURPLE.color!!) - @JvmField val YELLOW = rgb(ChatFormatting.YELLOW.color!!) - - @JvmField val LOW_POWER = RGBAColor(173, 41, 41) - @JvmField val FULL_POWER = RGBAColor(255, 242, 40) - @JvmField val LOW_MATTER = RGBAColor(0, 24, 148) - @JvmField val FULL_MATTER = RGBAColor(72, 90, 255) - @JvmField val LOW_PATTERNS = RGBAColor(44, 104, 57) - @JvmField val FULL_PATTERNS = RGBAColor(65, 255, 87) - - @JvmField val HALF_TRANSPARENT = RGBAColor(1f, 1f, 1f, 0.5f) - @JvmField val REDDISH = RGBAColor(1f, 0.4f, 0.4f) - - @JvmField - val CODECRGBA: Codec = RecordCodecBuilder.create { - it.group( - Codec.floatRange(0f, 1f).fieldOf("red").forGetter(RGBAColor::red), - Codec.floatRange(0f, 1f).fieldOf("green").forGetter(RGBAColor::green), - Codec.floatRange(0f, 1f).fieldOf("blue").forGetter(RGBAColor::blue), - Codec.floatRange(0f, 1f).optionalFieldOf("alpha", 1f).forGetter(RGBAColor::alpha), - ).apply(it, ::RGBAColor) - } - - @JvmField - val CODECRGB: Codec = RecordCodecBuilder.create { - it.group( - Codec.floatRange(0f, 1f).fieldOf("red").forGetter(RGBAColor::red), - Codec.floatRange(0f, 1f).fieldOf("green").forGetter(RGBAColor::green), - Codec.floatRange(0f, 1f).fieldOf("blue").forGetter(RGBAColor::blue), - ).apply(it, ::RGBAColor) - } - - fun rgb(color: Int): RGBAColor { - val r = (color and 0xFF0000 ushr 16) / 255f - val g = (color and 0xFF00 ushr 8) / 255f - val b = (color and 0xFF) / 255f - return RGBAColor(r, g, b) - } - - fun rgb(color: Long): RGBAColor { - val r = (color and 0xFF0000 ushr 16) / 255f - val g = (color and 0xFF00 ushr 8) / 255f - val b = (color and 0xFF) / 255f - return RGBAColor(r, g, b) - } - - fun bgr(color: Int): RGBAColor { - val r = (color and 0xFF0000 ushr 16) / 255f - val g = (color and 0xFF00 ushr 8) / 255f - val b = (color and 0xFF) / 255f - return RGBAColor(b, g, r) - } - - fun bgr(color: Long): RGBAColor { - val r = (color and 0xFF0000 ushr 16) / 255f - val g = (color and 0xFF00 ushr 8) / 255f - val b = (color and 0xFF) / 255f - return RGBAColor(b, g, r) - } - - fun abgr(color: Int): RGBAColor { - val r = (color and -0x1000000 ushr 24) / 255f - val g = (color and 0xFF0000 ushr 16) / 255f - val b = (color and 0xFF00 ushr 8) / 255f - val a = (color and 0xFF) / 255f - return RGBAColor(a, b, g, r) - } - - fun argb(color: Int): RGBAColor { - val a = (color and -0x1000000 ushr 24) / 255f - val r = (color and 0xFF0000 ushr 16) / 255f - val g = (color and 0xFF00 ushr 8) / 255f - val b = (color and 0xFF) / 255f - return RGBAColor(r, g, b, a) - } - - private val hexChars = CharAVLTreeSet() - - init { - "#0123456789abcdefABCDEF".forEach { hexChars.add(it) } - } - - fun isHexCharacter(char: Char): Boolean { - return char in hexChars - } - - private val shorthandRGBHex = Regex("#?([0-9abcdef])([0-9abcdef])([0-9abcdef])", RegexOption.IGNORE_CASE) - private val longhandRGBHex = Regex("#?([0-9abcdef]{2})([0-9abcdef]{2})([0-9abcdef]{2})", RegexOption.IGNORE_CASE) - - private val shorthandRGBAHex = Regex("#?([0-9abcdef])([0-9abcdef])([0-9abcdef])([0-9abcdef])", RegexOption.IGNORE_CASE) - private val longhandRGBAHex = Regex("#?([0-9abcdef]{2})([0-9abcdef]{2})([0-9abcdef]{2})([0-9abcdef]{2})", RegexOption.IGNORE_CASE) - - fun fromHexStringRGB(value: String): RGBAColor? { - if (value.length == 3 || value.length == 4) { - val match = shorthandRGBHex.find(value) ?: return null - val red = match.groupValues[1].toIntOrNull(16) ?: return null - val green = match.groupValues[2].toIntOrNull(16) ?: return null - val blue = match.groupValues[3].toIntOrNull(16) ?: return null - return RGBAColor(red * 16, green * 16, blue * 16) - } else if (value.length == 6 || value.length == 7) { - val match = longhandRGBHex.find(value) ?: return null - val red = match.groupValues[1].toIntOrNull(16) ?: return null - val green = match.groupValues[2].toIntOrNull(16) ?: return null - val blue = match.groupValues[3].toIntOrNull(16) ?: return null - return RGBAColor(red, green, blue) - } else { - return null - } - } - - fun fromHexStringRGBA(value: String): RGBAColor? { - if (value.length == 4 || value.length == 5) { - val match = shorthandRGBAHex.find(value) ?: return null - val red = match.groupValues[1].toIntOrNull(16) ?: return null - val green = match.groupValues[2].toIntOrNull(16) ?: return null - val blue = match.groupValues[3].toIntOrNull(16) ?: return null - val alpha = match.groupValues[4].toIntOrNull(16) ?: return null - return RGBAColor(red * 16, green * 16, blue * 16, alpha * 16) - } else if (value.length == 8 || value.length == 9) { - val match = longhandRGBAHex.find(value) ?: return null - val red = match.groupValues[1].toIntOrNull(16) ?: return null - val green = match.groupValues[2].toIntOrNull(16) ?: return null - val blue = match.groupValues[3].toIntOrNull(16) ?: return null - val alpha = match.groupValues[4].toIntOrNull(16) ?: return null - return RGBAColor(red, green, blue, alpha) - } else { - return null - } - } - } -} - -fun linearInterpolation(t: Float, a: RGBAColor, b: RGBAColor): RGBAColor { - return a.linearInterpolation(t, b) +@JvmField +val RGBColorDFUCodec: Codec = RecordCodecBuilder.create { + it.group( + Codec.floatRange(0f, 1f).fieldOf("red").forGetter(RGBAColor::red), + Codec.floatRange(0f, 1f).fieldOf("green").forGetter(RGBAColor::green), + Codec.floatRange(0f, 1f).fieldOf("blue").forGetter(RGBAColor::blue), + ).apply(it, ::RGBAColor) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CounterInvalidatedLazy.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CounterInvalidatedLazy.kt index aa398a7fd..908cfaaf6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CounterInvalidatedLazy.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CounterInvalidatedLazy.kt @@ -67,7 +67,7 @@ class CounterInvalidatedLazy(private val invalidator: IntSupplier, private va */ class SmartCounterInvalidatedLazy(invalidator: IntCounter, private val initializer: () -> V) : InvalidableLazy { init { - invalidator.addListener(IntConsumer { + invalidator.addListener(Runnable { stored = Companion }) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IntCounter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IntCounter.kt index 0c4c56e23..b9dab2547 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IntCounter.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IntCounter.kt @@ -1,12 +1,12 @@ package ru.dbotthepony.mc.otm.core.util -import ru.dbotthepony.mc.otm.core.IIntSubcripable -import ru.dbotthepony.mc.otm.core.ISubscriptable +import ru.dbotthepony.kommons.util.Listenable import java.util.function.BooleanSupplier +import java.util.function.Consumer import java.util.function.IntConsumer import java.util.function.IntSupplier -class IntCounter : IntSupplier, IIntSubcripable { +class IntCounter : IntSupplier, Listenable { /** * Doesn't subscribe to counter (counter does not reference this invalidator) */ @@ -26,9 +26,9 @@ class IntCounter : IntSupplier, IIntSubcripable { /** * Subscribes to counter (counter references this invalidator, can be removed using [remove]) */ - inner class StrongInvalidator : BooleanSupplier, ISubscriptable.L { + inner class StrongInvalidator : BooleanSupplier, Listenable.L { private var isValid = true - private val l = listeners.addListener(IntConsumer { isValid = false }) + private val l = listeners.addListener(Runnable { isValid = false }) override fun getAsBoolean(): Boolean { val isValid = isValid @@ -41,7 +41,7 @@ class IntCounter : IntSupplier, IIntSubcripable { } } - private val listeners = IIntSubcripable.Impl() + private val listeners = Listenable.Impl() private var value = 0 fun increment() { @@ -49,7 +49,11 @@ class IntCounter : IntSupplier, IIntSubcripable { listeners.accept(value) } - override fun addListener(listener: IntConsumer): ISubscriptable.L { + override fun addListener(listener: Consumer): Listenable.L { + return listeners.addListener(listener) + } + + override fun addListener(listener: Runnable): Listenable.L { return listeners.addListener(listener) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt index e348fb661..d422d6851 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Savetables.kt @@ -16,13 +16,11 @@ import net.minecraft.nbt.Tag import net.minecraft.resources.ResourceLocation import net.minecraftforge.common.util.INBTSerializable import org.apache.logging.log4j.LogManager -import ru.dbotthepony.mc.otm.core.GetterSetter -import ru.dbotthepony.mc.otm.core.asGetterSetter +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.nbt.set -import ru.dbotthepony.mc.otm.data.getOrNull import java.util.function.Supplier import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KProperty0 @@ -77,14 +75,14 @@ class Savetables : INBTSerializable { .withDeserializer { v, t -> v.deserializeNBT(t) } } - fun decimal(prop: GetterSetter, name: String, default: Decimal = Decimal.ZERO): Stateless { + fun decimal(prop: Delegate, name: String, default: Decimal = Decimal.ZERO): Stateless { return Stateless(prop, name, Tag::class.java) .withDeserializer { Decimal.deserializeNBT(it) } .withSerializer { it.serializeNBT() } .withDefault { default } } - fun decimalNullable(prop: GetterSetter, name: String, default: Decimal = Decimal.ZERO): Stateless { + fun decimalNullable(prop: Delegate, name: String, default: Decimal = Decimal.ZERO): Stateless { return Stateless(prop, name, Tag::class.java) .withDeserializer { Decimal.deserializeNBT(it) } .withSerializer { it?.serializeNBT() } @@ -92,7 +90,7 @@ class Savetables : INBTSerializable { } fun decimal(prop: KMutableProperty0, name: String = prop.name, default: Decimal = Decimal.ZERO): Stateless { - return decimal(prop.asGetterSetter(), name, default) + return decimal(Delegate.Of(prop), name, default) } fun decimalNullable(prop: KMutableProperty0, name: String = prop.name, default: Decimal = Decimal.ZERO): Stateless { @@ -102,87 +100,87 @@ class Savetables : INBTSerializable { .withDefault { default } } - fun float(prop: GetterSetter, name: String): Stateless { + fun float(prop: Delegate, name: String): Stateless { return Stateless(prop, name, NumericTag::class.java) .withSerializer { FloatTag.valueOf(it) } .withDeserializer { it.asFloat } } fun float(prop: KMutableProperty0, name: String = prop.name): Stateless { - return float(prop.asGetterSetter(), name) + return float(Delegate.Of(prop), name) } - fun double(prop: GetterSetter, name: String): Stateless { + fun double(prop: Delegate, name: String): Stateless { return Stateless(prop, name, NumericTag::class.java) .withSerializer { DoubleTag.valueOf(it) } .withDeserializer { it.asDouble } } fun double(prop: KMutableProperty0, name: String = prop.name): Stateless { - return double(prop.asGetterSetter(), name) + return double(Delegate.Of(prop), name) } - fun int(prop: GetterSetter, name: String): Stateless { + fun int(prop: Delegate, name: String): Stateless { return Stateless(prop, name, NumericTag::class.java) .withSerializer { IntTag.valueOf(it) } .withDeserializer { it.asInt } } fun int(prop: KMutableProperty0, name: String = prop.name): Stateless { - return int(prop.asGetterSetter(), name) + return int(Delegate.Of(prop), name) } - fun long(prop: GetterSetter, name: String): Stateless { + fun long(prop: Delegate, name: String): Stateless { return Stateless(prop, name, NumericTag::class.java) .withSerializer { LongTag.valueOf(it) } .withDeserializer { it.asLong } } fun long(prop: KMutableProperty0, name: String = prop.name): Stateless { - return long(prop.asGetterSetter(), name) + return long(Delegate.Of(prop), name) } - fun bool(prop: GetterSetter, name: String): Stateless { + fun bool(prop: Delegate, name: String): Stateless { return Stateless(prop, name, NumericTag::class.java) .withSerializer { ByteTag.valueOf(it) } .withDeserializer { it.asByte > 0 } } fun bool(prop: KMutableProperty0, name: String = prop.name): Stateless { - return bool(prop.asGetterSetter(), name) + return bool(Delegate.Of(prop), name) } - fun string(prop: GetterSetter, name: String): Stateless { + fun string(prop: Delegate, name: String): Stateless { return Stateless(prop, name, StringTag::class.java) .withSerializer { StringTag.valueOf(it) } .withDeserializer { it.asString } } fun string(prop: KMutableProperty0, name: String = prop.name): Stateless { - return string(prop.asGetterSetter(), name) + return string(Delegate.Of(prop), name) } - fun > enum(prop: GetterSetter, name: String, map: (String) -> E): Stateless { + fun > enum(prop: Delegate, name: String, map: (String) -> E): Stateless { return Stateless(prop, name, StringTag::class.java) .withSerializer { StringTag.valueOf(it.name) } .withDeserializer { map.invoke(it.asString) } } fun > enum(prop: KMutableProperty0, name: String = prop.name, map: (String) -> E): Stateless { - return enum(prop.asGetterSetter(), name, map) + return enum(Delegate.Of(prop), name, map) } - fun codecNullable(prop: GetterSetter, codec: Codec, name: String): Stateless { + fun codecNullable(prop: Delegate, codec: Codec, name: String): Stateless { return Stateless(prop, name, Tag::class.java) .withSerializer { prop.get()?.let { codec.encode(it, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow(false) { throw IllegalStateException("Failed to write NBT data for $name: $it") } } } .withDeserializer { codec.decode(NbtOps.INSTANCE, it).getOrThrow(false) { throw IllegalStateException("Failed to read NBT data for $name: $it") }.first } } fun codecNullable(prop: KMutableProperty0, codec: Codec, name: String = prop.name): Stateless { - return codecNullable(prop.asGetterSetter(), codec, name) + return codecNullable(Delegate.Of(prop), codec, name) } - fun codecNullable(prop: GetterSetter, codec: Codec, name: String, default: T?): Stateless { + fun codecNullable(prop: Delegate, codec: Codec, name: String, default: T?): Stateless { return Stateless(prop, name, Tag::class.java) .withSerializer { prop.get()?.let { codec.encode(it, NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow(false) { throw IllegalStateException("Failed to write NBT data for $name: $it") } } } .withDeserializer { codec.decode(NbtOps.INSTANCE, it).get().map({ it.first }, { LOGGER.error("Failed to read NBT data for $name", RuntimeException(it.message())); default }) } @@ -190,16 +188,16 @@ class Savetables : INBTSerializable { } fun codecNullable(prop: KMutableProperty0, codec: Codec, name: String = prop.name, default: T?): Stateless { - return codecNullable(prop.asGetterSetter(), codec, name, default) + return codecNullable(Delegate.Of(prop), codec, name, default) } - fun codec(prop: GetterSetter, codec: Codec, name: String): Stateless { + fun codec(prop: Delegate, codec: Codec, name: String): Stateless { return Stateless(prop, name, Tag::class.java) .withSerializer { codec.encode(prop.get(), NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow(false) { throw IllegalStateException("Failed to write NBT data for $name: $it") } } .withDeserializer { codec.decode(NbtOps.INSTANCE, it).getOrThrow(false) { throw IllegalStateException("Failed to read NBT data for $name: $it") }.first } } - fun codec(prop: GetterSetter, codec: Codec, name: String, default: T): Stateless { + fun codec(prop: Delegate, codec: Codec, name: String, default: T): Stateless { return Stateless(prop, name, Tag::class.java) .withSerializer { codec.encode(prop.get(), NbtOps.INSTANCE, NbtOps.INSTANCE.empty()).getOrThrow(false) { throw IllegalStateException("Failed to write NBT data for $name: $it") } } .withDeserializer { codec.decode(NbtOps.INSTANCE, it).get().map({ it.first }, { LOGGER.error("Failed to read NBT data for $name", RuntimeException(it.message())); default }) } @@ -207,27 +205,27 @@ class Savetables : INBTSerializable { } fun codec(prop: KMutableProperty0, codec: Codec, name: String = prop.name): Stateless { - return codec(prop.asGetterSetter(), codec, name) + return codec(Delegate.Of(prop), codec, name) } fun codec(prop: KMutableProperty0, codec: Codec, name: String = prop.name, default: T): Stateless { - return codec(prop.asGetterSetter(), codec, name, default) + return codec(Delegate.Of(prop), codec, name, default) } - fun vector(prop: GetterSetter, name: String, default: Vector = Vector.ZERO): Stateless { + fun vector(prop: Delegate, name: String, default: Vector = Vector.ZERO): Stateless { return codec(prop, Vector.CODEC, name, default) } fun vector(prop: KMutableProperty0, name: String = prop.name, default: Vector = Vector.ZERO): Stateless { - return vector(prop.asGetterSetter(), name, default) + return vector(Delegate.Of(prop), name, default) } - fun location(prop: GetterSetter, name: String): Stateless { + fun location(prop: Delegate, name: String): Stateless { return codec(prop, ResourceLocation.CODEC, name) } fun location(prop: KMutableProperty0, name: String = prop.name): Stateless { - return location(prop.asGetterSetter(), name) + return location(Delegate.Of(prop), name) } override fun serializeNBT(): CompoundTag { @@ -322,8 +320,8 @@ class Savetables : INBTSerializable { } } - inner class Stateless(private val prop: GetterSetter, override val name: String, override val type: Class) : Entry { - constructor(field: KMutableProperty0, name: String = field.name, type: Class) : this(field.asGetterSetter(), name, type) + inner class Stateless(private val prop: Delegate, override val name: String, override val type: Class) : Entry { + constructor(field: KMutableProperty0, name: String = field.name, type: Class) : this(Delegate.Of(field), name, type) init { check(!entries.any { it.name == name }) { "Already has entry with name $name!" } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/StreamCodecs.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/StreamCodecs.kt index 961847d1e..79c8db41b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/StreamCodecs.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/StreamCodecs.kt @@ -8,8 +8,15 @@ import com.mojang.serialization.DynamicOps import net.minecraft.nbt.NbtAccounter import net.minecraft.world.item.ItemStack import net.minecraftforge.fluids.FluidStack +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.io.StreamCodec +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.DelegateGetter +import ru.dbotthepony.kommons.util.DelegateSetter +import ru.dbotthepony.kommons.util.ListenableDelegate import ru.dbotthepony.mc.otm.core.immutableMap -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.readDecimal import ru.dbotthepony.mc.otm.core.math.writeDecimal import ru.dbotthepony.mc.otm.core.readItemType @@ -22,207 +29,34 @@ import java.io.InputStream import java.io.OutputStream import java.util.* import java.util.function.Predicate +import java.util.function.Supplier import kotlin.NoSuchElementException import kotlin.math.absoluteValue import kotlin.reflect.KClass -/** - * Represents value which can be encoded onto or decoded from stream. - * - * Also provides [copy] and [compare] methods - */ -interface IStreamCodec { - fun read(stream: DataInputStream): V - fun write(stream: DataOutputStream, value: V) +val ItemStackValueCodec = StreamCodec.Impl(DataInputStream::readItem, DataOutputStream::writeItem, ItemStack::copy) { a, b -> a.equals(b, true) } +val FluidStackValueCodec = StreamCodec.Impl(DataInputStream::readFluidStack, DataOutputStream::writeFluidStack, FluidStack::copy) { a, b -> a == b && a.amount == b.amount } +val ItemValueCodec = StreamCodec.Impl(DataInputStream::readItemType, DataOutputStream::writeItemType) { a, b -> a === b } +val DecimalValueCodec = StreamCodec.Impl(DataInputStream::readDecimal, DataOutputStream::writeDecimal) +val BigDecimalValueCodec = StreamCodec.Impl(DataInputStream::readBigDecimal, DataOutputStream::writeBigDecimal) +val ResourceLocationValueCodec = StreamCodec.Impl(DataInputStream::readResourceLocation, DataOutputStream::writeResourceLocation) - /** - * if value is immutable, return it right away - */ - fun copy(value: V): V - - /** - * Optional equality check override. Utilized to determine whenever e.g. network value is different from new value - * - * By default uses [Any.equals] - */ - fun compare(a: V, b: V): Boolean { - return a == b - } +fun DelegateSyncher.decimal(value: Decimal = Decimal.ZERO, setter: DelegateSetter = DelegateSetter.passthrough(), getter: DelegateGetter = DelegateGetter.passthrough()): DelegateSyncher.Slot { + return add(ListenableDelegate.maskSmart(value, getter, setter), DecimalValueCodec) } -class StreamCodec( - private val reader: (stream: DataInputStream) -> V, - private val writer: (stream: DataOutputStream, value: V) -> Unit, - private val copier: ((value: V) -> V) = { it }, - private val comparator: ((a: V, b: V) -> Boolean) = { a, b -> a == b } -) : IStreamCodec { - constructor( - reader: (stream: DataInputStream) -> V, - payloadSize: Long, - writer: (stream: DataOutputStream, value: V) -> Unit, - copier: ((value: V) -> V) = { it }, - comparator: ((a: V, b: V) -> Boolean) = { a, b -> a == b } - ) : this({ stream -> reader.invoke(stream) }, writer, copier, comparator) - - val nullable = object : IStreamCodec { - override fun read(stream: DataInputStream): V? { - return if (stream.read() == 0) null else reader.invoke(stream) - } - - override fun write(stream: DataOutputStream, value: V?) { - if (value === null) stream.write(0) else { - stream.write(1) - writer.invoke(stream, value) - } - } - - override fun copy(value: V?): V? { - return if (value === null) null else copier.invoke(value) - } - - override fun compare(a: V?, b: V?): Boolean { - if (a === null && b === null) return true - if (a === null || b === null) return false - return comparator.invoke(a, b) - } - } - - override fun read(stream: DataInputStream): V { - return reader.invoke(stream) - } - - override fun write(stream: DataOutputStream, value: V) { - writer.invoke(stream, value) - } - - override fun copy(value: V): V { - return copier.invoke(value) - } - - override fun compare(a: V, b: V): Boolean { - return comparator.invoke(a, b) - } +fun DelegateSyncher.computedDecimal(delegate: Supplier): DelegateSyncher.Slot { + return add(delegate, DecimalValueCodec) } -class CollectionStreamCodec>(val elementCodec: IStreamCodec, val collectionFactory: (Int) -> C) : IStreamCodec { - override fun read(stream: DataInputStream): C { - val size = stream.readVarIntLE() - - if (size <= 0) { - return collectionFactory.invoke(0) - } - - val collection = collectionFactory.invoke(size) - - for (i in 0 until size) { - collection.add(elementCodec.read(stream)) - } - - return collection - } - - override fun write(stream: DataOutputStream, value: C) { - stream.writeVarIntLE(value.size) - value.forEach { elementCodec.write(stream, it) } - } - - override fun copy(value: C): C { - val new = collectionFactory.invoke(value.size) - value.forEach { new.add(elementCodec.copy(it)) } - return new - } +fun DelegateSyncher.item(value: ItemStack = ItemStack.EMPTY, setter: DelegateSetter = DelegateSetter.passthrough(), getter: DelegateGetter = DelegateGetter.passthrough()): DelegateSyncher.Slot { + return add(ListenableDelegate.maskSmart(value, getter, setter), ItemStackValueCodec) } -val NullValueCodec = StreamCodec({ _ -> null }, { _, _ -> }) -val BooleanValueCodec = StreamCodec(DataInputStream::readBoolean, 1L, DataOutputStream::writeBoolean) { a, b -> a == b } -val ByteValueCodec = StreamCodec(DataInputStream::readByte, 1L, { s, v -> s.writeByte(v.toInt()) }) { a, b -> a == b } -val ShortValueCodec = StreamCodec(DataInputStream::readShort, 2L, { s, v -> s.writeShort(v.toInt()) }) { a, b -> a == b } -val IntValueCodec = StreamCodec(DataInputStream::readInt, 4L, DataOutputStream::writeInt) { a, b -> a == b } -val LongValueCodec = StreamCodec(DataInputStream::readLong, 8L, DataOutputStream::writeLong) { a, b -> a == b } -val FloatValueCodec = StreamCodec(DataInputStream::readFloat, 4L, DataOutputStream::writeFloat) { a, b -> a == b } -val DoubleValueCodec = StreamCodec(DataInputStream::readDouble, 8L, DataOutputStream::writeDouble) { a, b -> a == b } -val ItemStackValueCodec = StreamCodec(DataInputStream::readItem, DataOutputStream::writeItem, ItemStack::copy) { a, b -> a.equals(b, true) } -val FluidStackValueCodec = StreamCodec(DataInputStream::readFluidStack, DataOutputStream::writeFluidStack, FluidStack::copy) { a, b -> a == b && a.amount == b.amount } -val ItemValueCodec = StreamCodec(DataInputStream::readItemType, DataOutputStream::writeItemType) { a, b -> a === b } -val DecimalValueCodec = StreamCodec(DataInputStream::readDecimal, DataOutputStream::writeDecimal) -val BigDecimalValueCodec = StreamCodec(DataInputStream::readBigDecimal, DataOutputStream::writeBigDecimal) -val UUIDValueCodec = StreamCodec({ s -> UUID(s.readLong(), s.readLong()) }, { s, v -> s.writeLong(v.mostSignificantBits); s.writeLong(v.leastSignificantBits) }) -val VarIntValueCodec = StreamCodec(DataInputStream::readVarIntLE, DataOutputStream::writeVarIntLE) { a, b -> a == b } -val VarLongValueCodec = StreamCodec(DataInputStream::readVarLongLE, DataOutputStream::writeVarLongLE) { a, b -> a == b } -val BinaryStringCodec = StreamCodec(DataInputStream::readBinaryString, DataOutputStream::writeBinaryString) -val ResourceLocationValueCodec = StreamCodec(DataInputStream::readResourceLocation, DataOutputStream::writeResourceLocation) - -val RGBCodec: StreamCodec = StreamCodec( - { s -> RGBAColor(s.readFloat(), s.readFloat(), s.readFloat()) }, - { s, v -> s.writeFloat(v.red); s.writeFloat(v.green); s.writeFloat(v.blue) }) - -val RGBACodec: StreamCodec = StreamCodec( - { s -> RGBAColor(s.readFloat(), s.readFloat(), s.readFloat(), s.readFloat()) }, - { s, v -> s.writeFloat(v.red); s.writeFloat(v.green); s.writeFloat(v.blue); s.writeFloat(v.alpha) }) - -class EnumValueCodec>(clazz: Class) : IStreamCodec, Codec { - val clazz = searchClass(clazz) - val values: ImmutableList = ImmutableList.copyOf(this.clazz.enumConstants!!) - val valuesMap = immutableMap { - for (v in values) put(v.name, v) - } - - override fun read(stream: DataInputStream): V { - val id = stream.readVarIntLE() - return values.getOrNull(id) ?: throw NoSuchElementException("No such enum with index $id") - } - - override fun write(stream: DataOutputStream, value: V) { - stream.writeVarIntLE(value.ordinal) - } - - override fun copy(value: V): V { - return value - } - - override fun compare(a: V, b: V): Boolean { - return a === b - } - - override fun encode(input: V, ops: DynamicOps, prefix: T): DataResult { - if (ops.compressMaps()) { - return DataResult.success(ops.createInt(input.ordinal)) - } - - return DataResult.success(ops.createString(input.name)) - } - - override fun decode(ops: DynamicOps, input: T): DataResult> { - if (ops.compressMaps()) { - return ops.getNumberValue(input) - .flatMap { values.getOrNull(it.toInt())?.let { DataResult.success(Pair(it, ops.empty())) } ?: DataResult.error { "No such enum with ordinal index $it" } } - } - - return ops.getStringValue(input) - .flatMap { valuesMap[it]?.let { DataResult.success(Pair(it, ops.empty())) } ?: DataResult.error { "No such enum value $it" } } - } - - companion object { - /** - * FIXME: enums with abstract methods which get compiled to subclasses, whose DO NOT expose "parent's" enum constants array - * - * is there an already existing solution? - */ - fun > searchClass(clazz: Class): Class { - var search: Class<*> = clazz - - while (search.enumConstants == null && search.superclass != null) { - search = search.superclass - } - - if (search.enumConstants == null) { - throw ClassCastException("$clazz does not represent an enum or enum subclass") - } - - return search as Class - } - } +fun DelegateSyncher.computedItem(delegate: Supplier): DelegateSyncher.Slot { + return computed(delegate, ItemStackValueCodec) } -fun > Class.codec() = EnumValueCodec(this) -fun > KClass.codec() = EnumValueCodec(this.java) +fun DelegateSyncher.observedItem(value: ItemStack = ItemStack.EMPTY, setter: DelegateSetter = DelegateSetter.passthrough(), getter: DelegateGetter = DelegateGetter.passthrough()): DelegateSyncher.ObservedSlot { + return add(Delegate.maskSmart(value, getter, setter), ItemStackValueCodec) +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/armor/TritaniumArmorItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/armor/TritaniumArmorItem.kt index 2a1f8a588..402c60c0f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/armor/TritaniumArmorItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/armor/TritaniumArmorItem.kt @@ -13,7 +13,7 @@ import net.minecraftforge.client.extensions.common.IClientItemExtensions import net.minecraftforge.event.entity.living.LivingAttackEvent import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItems import java.util.function.Consumer diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt index eb629aabe..ed973cc3e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt @@ -24,7 +24,7 @@ import ru.dbotthepony.mc.otm.client.font import ru.dbotthepony.mc.otm.client.render.draw import ru.dbotthepony.mc.otm.client.render.renderRect import ru.dbotthepony.mc.otm.core.math.Angle -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.math.bezierCurve import ru.dbotthepony.mc.otm.core.math.component1 @@ -465,7 +465,7 @@ abstract class AbstractWeaponItem(val tables: KClass, pr renderRect(pose.last().pose(), -1f, -1f, 9f, 32f, color = heatBackground) val heat = item.heatProgress(stack, event.partialTick.toDouble()).toFloat() - renderRect(pose.last().pose(), 0f, 30f * (1f - heat), 7f, 30f * heat, color = linearInterpolation(heat, initialHeatColor, finalHeatColor)) + renderRect(pose.last().pose(), 0f, 30f * (1f - heat), 7f, 30f * heat, color = initialHeatColor.linearInterpolation(heat, finalHeatColor)) } pose.popPose() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterFunction.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterFunction.kt index b225a7c10..f7bf8df86 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterFunction.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterFunction.kt @@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.matter import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.registries.DeferredRegister +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.core.getValue import ru.dbotthepony.mc.otm.core.math.Decimal diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ISortingSettings.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ISortingSettings.kt index 8a6a4fe87..04d414327 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ISortingSettings.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ISortingSettings.kt @@ -4,6 +4,8 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack import net.minecraftforge.common.util.INBTSerializable +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.core.nbt.getBoolean import ru.dbotthepony.mc.otm.core.nbt.mapString import ru.dbotthepony.mc.otm.core.nbt.set @@ -58,8 +60,8 @@ interface IItemStackSortingSettings : IBaseSortingSettings { companion object { fun inputs(menu: MatteryMenu, observer: Runnable? = null) : IItemStackSortingSettings { return object : IItemStackSortingSettings { - override var isAscending: Boolean by BooleanInputWithFeedback(menu).also { if (observer != null) it.addListener { observer.run() } } - override var sorting: ItemStackSorter by EnumInputWithFeedback(menu).also { if (observer != null) it.addListener { observer.run() } } + override var isAscending: Boolean by BooleanInputWithFeedback(menu).also { if (observer != null) it.addListener(observer) } + override var sorting: ItemStackSorter by EnumInputWithFeedback(menu).also { if (observer != null) it.addListener(observer) } } } @@ -68,8 +70,8 @@ interface IItemStackSortingSettings : IBaseSortingSettings { return inputs(menu) return object : IItemStackSortingSettings { - override var isAscending: Boolean by BooleanInputWithFeedback(menu, parent::isAscending).also { if (observer != null) it.addListener { observer.run() } } - override var sorting: ItemStackSorter by EnumInputWithFeedback(menu, parent::sorting).also { if (observer != null) it.addListener { observer.run() } } + override var isAscending: Boolean by BooleanInputWithFeedback(menu, parent::isAscending).also { if (observer != null) it.addListener(observer) } + override var sorting: ItemStackSorter by EnumInputWithFeedback(menu, parent::sorting).also { if (observer != null) it.addListener(observer) } } } } @@ -106,8 +108,8 @@ interface IItemSortingSettings : IBaseSortingSettings { companion object { fun inputs(menu: MatteryMenu, observer: Runnable? = null) : IItemSortingSettings { return object : IItemSortingSettings { - override var isAscending: Boolean by BooleanInputWithFeedback(menu).also { if (observer != null) it.addListener { observer.run() } } - override var sorting: ItemSorter by EnumInputWithFeedback(menu).also { if (observer != null) it.addListener { observer.run() } } + override var isAscending: Boolean by BooleanInputWithFeedback(menu).also { if (observer != null) it.addListener(observer) } + override var sorting: ItemSorter by EnumInputWithFeedback(menu).also { if (observer != null) it.addListener(observer) } } } @@ -116,8 +118,8 @@ interface IItemSortingSettings : IBaseSortingSettings { return inputs(menu) return object : IItemSortingSettings { - override var isAscending: Boolean by BooleanInputWithFeedback(menu, parent::isAscending).also { if (observer != null) it.addListener { observer.run() } } - override var sorting: ItemSorter by EnumInputWithFeedback(menu, parent::sorting).also { if (observer != null) it.addListener { observer.run() } } + override var isAscending: Boolean by BooleanInputWithFeedback(menu, parent::isAscending).also { if (observer != null) it.addListener(observer) } + override var sorting: ItemSorter by EnumInputWithFeedback(menu, parent::sorting).also { if (observer != null) it.addListener(observer) } } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt index 89c3636fe..577b9c11e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -24,6 +24,16 @@ import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack import net.minecraft.world.item.enchantment.EnchantmentHelper.hasBindingCurse import net.minecraft.world.level.block.entity.BlockEntity +import ru.dbotthepony.kommons.io.BinaryStringCodec +import ru.dbotthepony.kommons.io.BooleanValueCodec +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.io.FloatValueCodec +import ru.dbotthepony.kommons.io.NullValueCodec +import ru.dbotthepony.kommons.io.StreamCodec +import ru.dbotthepony.kommons.io.VarIntValueCodec +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.UpgradeType @@ -38,21 +48,16 @@ import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.UpgradeContainer import ru.dbotthepony.mc.otm.container.computeSortedIndices import ru.dbotthepony.mc.otm.container.sortWithIndices -import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.collect.ConditionalEnumSet import ru.dbotthepony.mc.otm.core.collect.ConditionalSet import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.util.BigDecimalValueCodec -import ru.dbotthepony.mc.otm.core.util.BinaryStringCodec -import ru.dbotthepony.mc.otm.core.util.BooleanValueCodec -import ru.dbotthepony.mc.otm.core.util.CollectionStreamCodec -import ru.dbotthepony.mc.otm.core.util.FloatValueCodec -import ru.dbotthepony.mc.otm.core.util.IStreamCodec +import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec import ru.dbotthepony.mc.otm.core.util.ItemStackValueCodec import ru.dbotthepony.mc.otm.core.util.ItemValueCodec -import ru.dbotthepony.mc.otm.core.util.NullValueCodec -import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec +import ru.dbotthepony.mc.otm.core.util.computedDecimal +import ru.dbotthepony.mc.otm.core.util.computedItem import ru.dbotthepony.mc.otm.menu.input.InstantBooleanInput import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.network.MNetworkContext @@ -60,9 +65,6 @@ import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.network.MenuFieldPacket import ru.dbotthepony.mc.otm.network.MenuNetworkChannel import ru.dbotthepony.mc.otm.network.SetCarriedPacket -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer -import ru.dbotthepony.mc.otm.network.synchronizer.IField -import ru.dbotthepony.mc.otm.network.synchronizer.IMutableBooleanField import java.io.DataInputStream import java.io.DataOutputStream import java.math.BigDecimal @@ -87,7 +89,7 @@ data class EquipmentSlots( data class UpgradeSlots( val slots: List, val allowedTypes: Set, - val openState: GetterSetter, + val openState: Delegate, val currentStats: IMatteryUpgrade ) @@ -100,7 +102,8 @@ abstract class MatteryMenu( /** * Server->Client synchronizer */ - val mSynchronizer = FieldSynchronizer() + val mSynchronizer = DelegateSyncher() + val synchronizerRemote = mSynchronizer.Remote() val player: Player get() = inventory.player private val _playerInventorySlots = ArrayList() @@ -131,9 +134,9 @@ abstract class MatteryMenu( /** * Client->Server input */ - inner class PlayerInput(val codec: IStreamCodec, allowSpectators: Boolean = false, val handler: (V) -> Unit) : Consumer, Predicate { + inner class PlayerInput(val codec: StreamCodec, allowSpectators: Boolean = false, val handler: (V) -> Unit) : Consumer, Predicate { val id = playerInputs.size - var allowSpectators by mSynchronizer.bool(allowSpectators).property + var allowSpectators by mSynchronizer.boolean(allowSpectators) init { playerInputs.add(this) @@ -169,7 +172,7 @@ abstract class MatteryMenu( } inner class SortInput(val container: Container, val settings: IItemStackSortingSettings) { - val input = PlayerInput(CollectionStreamCodec(VarIntValueCodec, ::IntArrayList)) { + val input = PlayerInput(StreamCodec.Collection(VarIntValueCodec, ::IntArrayList)) { container.sortWithIndices(it) } @@ -185,6 +188,7 @@ abstract class MatteryMenu( } fun bigDecimalInput(allowSpectators: Boolean = false, handler: (BigDecimal) -> Unit) = PlayerInput(BigDecimalValueCodec, allowSpectators, handler) + fun decimalInput(allowSpectators: Boolean = false, handler: (Decimal) -> Unit) = PlayerInput(DecimalValueCodec, allowSpectators, handler) fun booleanInput(allowSpectators: Boolean = false, handler: (Boolean) -> Unit) = PlayerInput(BooleanValueCodec, allowSpectators, handler) fun itemInput(allowSpectators: Boolean = false, handler: (Item) -> Unit) = PlayerInput(ItemValueCodec, allowSpectators, handler) fun itemStackInput(allowSpectators: Boolean = false, handler: (ItemStack) -> Unit) = PlayerInput(ItemStackValueCodec, allowSpectators, handler) @@ -229,11 +233,11 @@ abstract class MatteryMenu( protected var inventorySlotIndexStart = 0 protected var inventorySlotIndexEnd = 0 - fun addFilterSlots(slots: ItemFilter): List> { - val result = ArrayList>(slots.size) + fun addFilterSlots(slots: ItemFilter): List> { + val result = ArrayList>(slots.size) for (i in 0 until slots.size) { - result.add(GetterSetter.of( + result.add(Delegate.Of( mSynchronizer.computedItem { slots[i] }, itemStackInput { slots[i] = it } )) @@ -242,11 +246,11 @@ abstract class MatteryMenu( return result } - fun addFilterSlots(amount: Int): List> { - val result = ArrayList>(amount) + fun addFilterSlots(amount: Int): List> { + val result = ArrayList>(amount) for (i in 0 until amount) { - result.add(GetterSetter.of( + result.add(Delegate.Of( mSynchronizer.computedItem { ItemStack.EMPTY }, itemStackInput { throw UnsupportedOperationException() } )) @@ -255,7 +259,7 @@ abstract class MatteryMenu( return result } - fun addFilterSlots(slots: ItemFilter?, amount: Int): List> { + fun addFilterSlots(slots: ItemFilter?, amount: Int): List> { if (slots != null && amount != slots.size) throw IllegalStateException("Provided ItemFiler has different amount of slots than expected: ${slots.size} != $amount") @@ -274,7 +278,7 @@ abstract class MatteryMenu( return !isInventorySlotLocked(index) && super.mayPickup(player) } - var chargeFlag: GetterSetter? = null + var chargeFlag: Delegate? = null private set init { @@ -283,13 +287,13 @@ abstract class MatteryMenu( if (addFilter) { val mContainer = container as IMatteryContainer - filter = GetterSetter.of( + filter = Delegate.Of( getter = { mContainer.getSlotFilter(slotIndex) }, setter = nullableItemInput(true) { mContainer.setSlotFilter(slotIndex, it) }::accept ) } - chargeFlag = GetterSetter.of( + chargeFlag = Delegate.Of( getter = { slotIndex in mattery.slotsChargeFlag }, setter = booleanInput(true) { if (mattery.hasExopack) { if (it) mattery.slotsChargeFlag.add(slotIndex) else mattery.slotsChargeFlag.remove(slotIndex) } }::accept ) @@ -379,7 +383,7 @@ abstract class MatteryMenu( protected fun matteryBroadcast() { beforeBroadcast() - val payload = mSynchronizer.collectNetworkPayload() + val payload = synchronizerRemote.write() if (payload != null) { if (broadcastOnce) { @@ -398,7 +402,7 @@ abstract class MatteryMenu( } override fun broadcastFullState() { - mSynchronizer.invalidate() + synchronizerRemote.invalidate() super.broadcastFullState() matteryBroadcast() } @@ -437,17 +441,17 @@ abstract class MatteryMenu( val container = pSlot.container val input: PlayerInput - val field: IField + val field: Delegate if (container is IMatteryContainer) { input = PlayerInput(ItemValueCodec.nullable, handler = { container.setSlotFilter(pSlot.slotIndex, it) }) - field = mSynchronizer.ComputedField(getter = { container.getSlotFilter(pSlot.slotIndex) }, ItemValueCodec.nullable) + field = mSynchronizer.add(delegate = { container.getSlotFilter(pSlot.slotIndex) }, ItemValueCodec.nullable) } else { input = PlayerInput(ItemValueCodec.nullable, handler = { throw UnsupportedOperationException() }) - field = mSynchronizer.ComputedField(getter = { null }, ItemValueCodec.nullable) + field = mSynchronizer.add(delegate = { null }, ItemValueCodec.nullable) } - pSlot.filter = GetterSetter.of(getter = field::value, setter = input::accept) + pSlot.filter = Delegate.Of(getter = field::get, setter = input::accept) } return super.addSlot(pSlot) @@ -777,14 +781,14 @@ abstract class MatteryMenu( require(count == container.containerSize) { "Upgrade container size ${container.containerSize} does not match with provided size $count" } } - val allowedTypes = EnumMap(UpgradeType::class.java) + val allowedTypes = EnumMap(UpgradeType::class.java) for (value in UpgradeType.ALL) { - allowedTypes[value] = mSynchronizer.bool() - - if (container != null) { - allowedTypes[value]!!.boolean = value in container.allowedUpgrades - } + allowedTypes[value] = mSynchronizer.boolean().delegate.also { + if (container != null) { + it.accept(value in container.allowedUpgrades) + } + }::get as BooleanSupplier } val syncContainer = container ?: SimpleContainer(count) @@ -799,7 +803,7 @@ abstract class MatteryMenu( } override fun mayPlace(itemStack: ItemStack): Boolean { - return super.mayPlace(itemStack) && itemStack.getCapability(MatteryCapability.UPGRADE).map { it.upgradeTypes.any { allowedTypes[it]!!.boolean } }.orElse(false) + return super.mayPlace(itemStack) && itemStack.getCapability(MatteryCapability.UPGRADE).map { it.upgradeTypes.any { allowedTypes[it]!!.asBoolean } }.orElse(false) } } }.also { for (i in it.indices.reversed()) addStorageSlot(it[i], prepend = true, condition = isOpen) }, @@ -808,14 +812,14 @@ abstract class MatteryMenu( openState = isOpen, currentStats = object : IMatteryUpgrade { override val upgradeTypes: Set = setOf() - override val speedBonus: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.speedBonus ?: 0.0 }).property - override val processingItems: Int by mSynchronizer.computedInt(IntSupplier { container?.processingItems ?: 0 }).property + override val speedBonus: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.speedBonus ?: 0.0 }) + override val processingItems: Int by mSynchronizer.computedInt(IntSupplier { container?.processingItems ?: 0 }) override val energyStorageFlat: Decimal by mSynchronizer.computedDecimal { container?.energyStorageFlat ?: Decimal.ZERO } override val energyStorage: Decimal by mSynchronizer.computedDecimal { container?.energyStorage ?: Decimal.ZERO } override val energyConsumed: Decimal by mSynchronizer.computedDecimal { container?.energyConsumed ?: Decimal.ZERO } override val energyThroughputFlat: Decimal by mSynchronizer.computedDecimal { container?.energyThroughputFlat ?: Decimal.ZERO } override val energyThroughput: Decimal by mSynchronizer.computedDecimal { container?.energyThroughput ?: Decimal.ZERO } - override val failureMultiplier: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.failureMultiplier ?: 1.0 }).property + override val failureMultiplier: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.failureMultiplier ?: 1.0 }) } ) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt index 69b2b53d1..c7995158a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt @@ -8,13 +8,12 @@ import net.minecraft.world.inventory.Slot import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack import net.minecraftforge.common.capabilities.ForgeCapabilities +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.container.IMatteryContainer -import ru.dbotthepony.mc.otm.container.MatteryContainer -import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.runOnClient import java.util.function.Predicate @@ -73,7 +72,7 @@ open class UserFilteredSlot(container: Container, index: Int, x: Int = 0, y: Int var hasSetFilter = false private set - var filter: GetterSetter? = null + var filter: Delegate? = null set(value) { hasSetFilter = true field = value diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/CargoCrateMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/CargoCrateMenu.kt index eb438a19b..bca819c2b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/CargoCrateMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/CargoCrateMenu.kt @@ -4,12 +4,7 @@ import net.minecraft.world.Container import net.minecraft.world.SimpleContainer import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player -import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity -import ru.dbotthepony.mc.otm.capability.matteryPlayer -import ru.dbotthepony.mc.otm.container.sort -import ru.dbotthepony.mc.otm.core.util.NullValueCodec -import ru.dbotthepony.mc.otm.menu.IItemStackSortingSettings import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.UserFilteredSlot import ru.dbotthepony.mc.otm.menu.makeSlots diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/MinecartCargoCrateMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/MinecartCargoCrateMenu.kt index b4aa8d957..beb40eb49 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/MinecartCargoCrateMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/MinecartCargoCrateMenu.kt @@ -5,8 +5,6 @@ import net.minecraft.world.SimpleContainer import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity -import ru.dbotthepony.mc.otm.container.sort -import ru.dbotthepony.mc.otm.core.util.NullValueCodec import ru.dbotthepony.mc.otm.entity.MinecartCargoCrate import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatterySlot diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/PainterMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/PainterMenu.kt index 6e4f94e7c..c72acbe93 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/PainterMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/PainterMenu.kt @@ -9,10 +9,13 @@ import net.minecraft.world.level.material.Fluids import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.fluids.FluidStack import net.minecraftforge.fluids.capability.IFluidHandler +import ru.dbotthepony.kommons.util.Listenable +import ru.dbotthepony.kommons.util.ListenableDelegate +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.container.MatteryContainer -import ru.dbotthepony.mc.otm.core.ISubscriptable import ru.dbotthepony.mc.otm.core.addAll import ru.dbotthepony.mc.otm.core.collect.SupplierMap import ru.dbotthepony.mc.otm.core.collect.filter @@ -27,14 +30,14 @@ import ru.dbotthepony.mc.otm.recipe.AbstractPainterRecipe import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MRecipes import java.util.* -import java.util.function.IntConsumer +import java.util.function.IntSupplier import kotlin.collections.ArrayList class PainterMenu( containerId: Int, inventory: Inventory, tile: PainterBlockEntity? = null ) : MatteryMenu(MMenus.PAINTER, containerId, inventory, tile) { val dyeStored = (DyeColor.entries.toMutableList().also { it.add(0, null) }).associateWith { dye -> - mSynchronizer.ComputedIntField({ tile?.dyeStored(dye) ?: 0 }).also { it.addListener(IntConsumer { rescan() }) } + mSynchronizer.computedInt(IntSupplier { tile?.dyeStored(dye) ?: 0 }).also { it.addListener(Runnable { rescan() }) } } val dyeStoredDirect = SupplierMap(dyeStored) @@ -43,7 +46,7 @@ class PainterMenu( val inputContainer = MatteryContainer(::rescan, 1) val outputContainer = MatteryContainer(1) private var lastRecipe: RecipeHolder? = null - var selectedRecipe by mSynchronizer.Field(null, ResourceLocationValueCodec.nullable).also { it.addListener { rescan() } } + var selectedRecipe by mSynchronizer.Slot(ListenableDelegate.Box(null), ResourceLocationValueCodec.nullable).also { it.addListener(Runnable { rescan() }) } val isBulk = BooleanInputWithFeedback(this, tile?.let { it::isBulk }) @@ -123,14 +126,14 @@ class PainterMenu( clearContainer(p_38940_, inputContainer) } - val listeners = ISubscriptable.Impl() + val listeners = Listenable.Void() val possibleRecipes = ArrayList>() private fun rescan() { possibleRecipes.clear() possibleRecipes.addAll(inventory.player.level().recipeManager.byType(MRecipes.PAINTER).values.iterator().filter { it.value.matches(inputContainer[0]) }) - listeners.accept(Unit) + listeners.run() if (tile !is PainterBlockEntity) return if (inputContainer.isEmpty || selectedRecipe == null) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractPlayerInputWithFeedback.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractPlayerInputWithFeedback.kt index 66c9fbfc8..71d56932b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractPlayerInputWithFeedback.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractPlayerInputWithFeedback.kt @@ -1,11 +1,10 @@ package ru.dbotthepony.mc.otm.menu.input import net.minecraft.world.entity.player.Player -import ru.dbotthepony.mc.otm.core.GetterSetter -import ru.dbotthepony.mc.otm.core.ISubscriptable -import ru.dbotthepony.mc.otm.core.SentientGetterSetter +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.Listenable +import ru.dbotthepony.kommons.util.ListenableDelegate import ru.dbotthepony.mc.otm.menu.MatteryMenu -import ru.dbotthepony.mc.otm.network.synchronizer.IField import java.util.function.Consumer import java.util.function.Predicate import java.util.function.Supplier @@ -16,7 +15,7 @@ import kotlin.reflect.KMutableProperty0 * * Getting and setting values should ONLY be done clientside */ -interface IPlayerInputWithFeedback : SentientGetterSetter, Predicate +interface IPlayerInputWithFeedback : ListenableDelegate, Predicate /** * Represents Server to Client synchronization and Client to Server input @@ -25,13 +24,13 @@ interface IPlayerInputWithFeedback : SentientGetterSetter, Predicate : IPlayerInputWithFeedback { abstract val input: MatteryMenu.PlayerInput - abstract val field: IField + abstract val field: ListenableDelegate - final override fun addListener(listener: Consumer): ISubscriptable.L { + final override fun addListener(listener: Consumer): Listenable.L { return field.addListener(listener) } - val value: V get() = this.field.value + val value: V get() = this.field.get() final override fun get(): V { return value @@ -73,7 +72,7 @@ abstract class AbstractPlayerInputWithFeedback : IPlayerInputWithFeedback return this } - fun with(state: GetterSetter): AbstractPlayerInputWithFeedback { + fun with(state: Delegate): AbstractPlayerInputWithFeedback { withConsumer(state) withSupplier(state) return this diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/BooleanInputWithFeedback.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/BooleanInputWithFeedback.kt index b90ab2934..ff3eba3ca 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/BooleanInputWithFeedback.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/BooleanInputWithFeedback.kt @@ -1,20 +1,20 @@ package ru.dbotthepony.mc.otm.menu.input -import ru.dbotthepony.mc.otm.core.GetterSetter +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.menu.MatteryMenu import java.util.function.BooleanSupplier import kotlin.reflect.KMutableProperty0 class BooleanInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean = false) : AbstractPlayerInputWithFeedback() { override val input = menu.booleanInput(allowSpectators) { consumer?.invoke(it) } - override val field = menu.mSynchronizer.computedBool(BooleanSupplier { supplier?.invoke() ?: false }) + override val field = menu.mSynchronizer.computedBoolean(BooleanSupplier { supplier?.invoke() ?: false }) constructor(menu: MatteryMenu, allowSpectators: Boolean, state: KMutableProperty0?) : this(menu, allowSpectators) { if (state != null) with(state) } - constructor(menu: MatteryMenu, allowSpectators: Boolean, state: GetterSetter?) : this(menu, allowSpectators) { + constructor(menu: MatteryMenu, allowSpectators: Boolean, state: Delegate?) : this(menu, allowSpectators) { if (state != null) with(state) } @@ -24,7 +24,7 @@ class BooleanInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean = fal with(state) } - constructor(menu: MatteryMenu, state: GetterSetter?) : this(menu) { + constructor(menu: MatteryMenu, state: Delegate?) : this(menu) { if (state != null) with(state) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnergyConfigPlayerInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnergyConfigPlayerInput.kt index 0205c1d57..a04f1647d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnergyConfigPlayerInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnergyConfigPlayerInput.kt @@ -1,5 +1,7 @@ package ru.dbotthepony.mc.otm.menu.input +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.core.immutableMap @@ -15,7 +17,7 @@ class EnergyConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockE val push = BooleanInputWithFeedback(menu) val input = EnumInputWithFeedback(menu) - var possibleModes by menu.mSynchronizer.enum(FlowDirection::class.java) + var possibleModes by menu.mSynchronizer.enum(FlowDirection.NONE) private set var default by menu.mSynchronizer.enum(FlowDirection.NONE) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnumInputWithFeedback.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnumInputWithFeedback.kt index 8d26f352e..d8f7d05b8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnumInputWithFeedback.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/EnumInputWithFeedback.kt @@ -1,24 +1,24 @@ package ru.dbotthepony.mc.otm.menu.input -import ru.dbotthepony.mc.otm.core.GetterSetter -import ru.dbotthepony.mc.otm.core.util.EnumValueCodec +import ru.dbotthepony.kommons.io.StreamCodec +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.menu.MatteryMenu import kotlin.reflect.KMutableProperty0 inline fun > EnumInputWithFeedback(menu: MatteryMenu, allowedValues: Set? = null) = EnumInputWithFeedback(menu, E::class.java, allowedValues = allowedValues) inline fun > EnumInputWithFeedback(menu: MatteryMenu, state: KMutableProperty0?, allowedValues: Set? = null) = EnumInputWithFeedback(menu, E::class.java, state, allowedValues = allowedValues) -inline fun > EnumInputWithFeedback(menu: MatteryMenu, state: GetterSetter?, allowedValues: Set? = null) = EnumInputWithFeedback(menu, E::class.java, state, allowedValues = allowedValues) +inline fun > EnumInputWithFeedback(menu: MatteryMenu, state: Delegate?, allowedValues: Set? = null) = EnumInputWithFeedback(menu, E::class.java, state, allowedValues = allowedValues) inline fun > EnumInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean, allowedValues: Set? = null) = EnumInputWithFeedback(menu, E::class.java, allowSpectators, allowedValues = allowedValues) inline fun > EnumInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean, state: KMutableProperty0?, allowedValues: Set? = null) = EnumInputWithFeedback(menu, E::class.java, allowSpectators, state, allowedValues = allowedValues) -inline fun > EnumInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean, state: GetterSetter?, allowedValues: Set? = null) = EnumInputWithFeedback(menu, E::class.java, allowSpectators, state, allowedValues = allowedValues) +inline fun > EnumInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean, state: Delegate?, allowedValues: Set? = null) = EnumInputWithFeedback(menu, E::class.java, allowSpectators, state, allowedValues = allowedValues) class EnumInputWithFeedback>(menu: MatteryMenu, clazz: Class, allowSpectators: Boolean = false, val allowedValues: Set? = null) : AbstractPlayerInputWithFeedback() { - val codec = EnumValueCodec(clazz) + val codec = StreamCodec.Enum(clazz) private val default = codec.values.first() override val input = menu.PlayerInput(codec, allowSpectators) { if (allowedValues == null || it in allowedValues) consumer?.invoke(it) } - override val field = menu.mSynchronizer.ComputedField(getter = { supplier?.invoke() ?: default }, codec) + override val field = menu.mSynchronizer.computed(delegate = { supplier?.invoke() ?: default }, codec) constructor(menu: MatteryMenu, clazz: Class, state: KMutableProperty0?, allowedValues: Set? = null) : this(menu, clazz, allowedValues = allowedValues) { if (state != null) { @@ -26,7 +26,7 @@ class EnumInputWithFeedback>(menu: MatteryMenu, clazz: Class, all } } - constructor(menu: MatteryMenu, clazz: Class, state: GetterSetter?, allowedValues: Set? = null) : this(menu, clazz, allowedValues = allowedValues) { + constructor(menu: MatteryMenu, clazz: Class, state: Delegate?, allowedValues: Set? = null) : this(menu, clazz, allowedValues = allowedValues) { if (state != null) { with(state) } @@ -38,7 +38,7 @@ class EnumInputWithFeedback>(menu: MatteryMenu, clazz: Class, all } } - constructor(menu: MatteryMenu, clazz: Class, allowSpectators: Boolean, state: GetterSetter?, allowedValues: Set? = null) : this(menu, clazz, allowSpectators, allowedValues = allowedValues) { + constructor(menu: MatteryMenu, clazz: Class, allowSpectators: Boolean, state: Delegate?, allowedValues: Set? = null) : this(menu, clazz, allowSpectators, allowedValues = allowedValues) { if (state != null) { with(state) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FloatInputWithFeedback.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FloatInputWithFeedback.kt index 8ebb92db2..400450cdf 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FloatInputWithFeedback.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FloatInputWithFeedback.kt @@ -1,6 +1,6 @@ package ru.dbotthepony.mc.otm.menu.input -import ru.dbotthepony.mc.otm.core.GetterSetter +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.menu.MatteryMenu import kotlin.reflect.KMutableProperty0 @@ -12,7 +12,7 @@ class FloatInputWithFeedback(menu: MatteryMenu) : AbstractPlayerInputWithFeedbac with(state) } - constructor(menu: MatteryMenu, state: GetterSetter) : this(menu) { + constructor(menu: MatteryMenu, state: Delegate) : this(menu) { with(state) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FluidConfigPlayerInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FluidConfigPlayerInput.kt index b7c33511e..bad7e36a7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FluidConfigPlayerInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/FluidConfigPlayerInput.kt @@ -1,5 +1,7 @@ package ru.dbotthepony.mc.otm.menu.input +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.core.immutableMap @@ -10,7 +12,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryMenu * [allowPull] and [allowPush] controls whenever player is allowed to change these options */ class FluidConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockEntity.ConfigurableFluidHandler<*>? = null, val allowPull: Boolean = false, val allowPush: Boolean = false) { - var possibleModes by menu.mSynchronizer.enum(FlowDirection::class.java) + var possibleModes by menu.mSynchronizer.enum(FlowDirection.NONE) private set inner class Piece(val side: RelativeSide) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt index 2b1b7e85c..de588058c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt @@ -1,10 +1,10 @@ package ru.dbotthepony.mc.otm.menu.input -import ru.dbotthepony.mc.otm.core.GetterSetter +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.menu.MatteryMenu import java.util.function.BooleanSupplier -class InstantBooleanInput(menu: MatteryMenu) : GetterSetter, BooleanSupplier { +class InstantBooleanInput(menu: MatteryMenu) : Delegate, BooleanSupplier { var value = false private set diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/IntInputWithFeedback.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/IntInputWithFeedback.kt index 5f1e9bfcd..ca967b85e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/IntInputWithFeedback.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/IntInputWithFeedback.kt @@ -1,6 +1,6 @@ package ru.dbotthepony.mc.otm.menu.input -import ru.dbotthepony.mc.otm.core.GetterSetter +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.menu.MatteryMenu import java.util.function.IntSupplier import kotlin.reflect.KMutableProperty0 @@ -14,7 +14,7 @@ class IntInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean = false) with(state) } - constructor(menu: MatteryMenu, allowSpectators: Boolean, state: GetterSetter?) : this(menu, allowSpectators) { + constructor(menu: MatteryMenu, allowSpectators: Boolean, state: Delegate?) : this(menu, allowSpectators) { if (state != null) with(state) } @@ -24,7 +24,7 @@ class IntInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean = false) with(state) } - constructor(menu: MatteryMenu, state: GetterSetter?) : this(menu) { + constructor(menu: MatteryMenu, state: Delegate?) : this(menu) { if (state != null) with(state) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemConfigPlayerInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemConfigPlayerInput.kt index 8c6216f03..aee23e740 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemConfigPlayerInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/ItemConfigPlayerInput.kt @@ -1,5 +1,7 @@ package ru.dbotthepony.mc.otm.menu.input +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.core.immutableMap @@ -10,8 +12,8 @@ import ru.dbotthepony.mc.otm.menu.MatteryMenu * [allowPull] and [allowPush] controls whenever player is allowed to change these options */ class ItemConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockEntity.ConfigurableItemHandler? = null, val allowPull: Boolean = false, val allowPush: Boolean = false) { - private val allowedFlags = MatteryDeviceBlockEntity.ItemHandlerMode.values().map { menu.mSynchronizer.bool() to it } - fun isAllowed(value: MatteryDeviceBlockEntity.ItemHandlerMode) = allowedFlags[value.ordinal].first.boolean + private val allowedFlags = MatteryDeviceBlockEntity.ItemHandlerMode.values().map { menu.mSynchronizer.boolean() to it } + fun isAllowed(value: MatteryDeviceBlockEntity.ItemHandlerMode) = allowedFlags[value.ordinal].first.get() inner class Piece(val side: RelativeSide) { fun isAllowed(value: MatteryDeviceBlockEntity.ItemHandlerMode) = this@ItemConfigPlayerInput.isAllowed(value) @@ -38,7 +40,7 @@ class ItemConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockEnt fun with(config: MatteryDeviceBlockEntity.ConfigurableItemHandler) { for ((f, v) in allowedFlags) { - f.boolean = v in config.possibleViews + f.accept(v in config.possibleViews) } for ((side, v) in config.pieces) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/StringInputWithFeedback.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/StringInputWithFeedback.kt index 617bd9dfc..015935e3d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/StringInputWithFeedback.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/StringInputWithFeedback.kt @@ -1,6 +1,6 @@ package ru.dbotthepony.mc.otm.menu.input -import ru.dbotthepony.mc.otm.core.GetterSetter +import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.mc.otm.menu.MatteryMenu import kotlin.reflect.KMutableProperty0 @@ -12,7 +12,7 @@ class StringInputWithFeedback(menu: MatteryMenu) : AbstractPlayerInputWithFeedba with(state) } - constructor(menu: MatteryMenu, state: GetterSetter) : this(menu) { + constructor(menu: MatteryMenu, state: Delegate) : this(menu) { with(state) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt index 1827a4877..451b0549b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt @@ -6,6 +6,9 @@ import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.item.Item import org.apache.logging.log4j.LogManager +import ru.dbotthepony.kommons.io.NullValueCodec +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.matter.MatterPanelBlockEntity import ru.dbotthepony.mc.otm.capability.matter.* import ru.dbotthepony.mc.otm.client.minecraft @@ -13,7 +16,6 @@ import ru.dbotthepony.mc.otm.core.addSorted import ru.dbotthepony.mc.otm.core.map import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec -import ru.dbotthepony.mc.otm.core.util.NullValueCodec import ru.dbotthepony.mc.otm.core.util.writeCollection import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphListener import ru.dbotthepony.mc.otm.graph.matter.MatterGraph @@ -141,8 +143,8 @@ class MatterPanelMenu( var isProvidingTasks by BooleanInputWithFeedback(this, tile?.let { it::isProvidingTasks }) val cancelAll = PlayerInput(NullValueCodec) { tile?.dropAllTasks() } - val totalMatterStored: Decimal by mSynchronizer.ComputedField( - getter = { tile?.matterNode?.graph?.getMatterStorageLevel() ?: Decimal.ZERO }, + val totalMatterStored: Decimal by mSynchronizer.computed( + delegate = { tile?.matterNode?.graph?.getMatterStorageLevel() ?: Decimal.ZERO }, codec = DecimalValueCodec, ) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/DriveViewerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/DriveViewerMenu.kt index 9a24e4021..ff2b8e2a7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/DriveViewerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/DriveViewerMenu.kt @@ -5,16 +5,18 @@ import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.item.ItemStack import net.minecraftforge.common.capabilities.ForgeCapabilities +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.storage.DriveViewerBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage import ru.dbotthepony.mc.otm.container.ItemFilter -import ru.dbotthepony.mc.otm.core.GetterSetter -import ru.dbotthepony.mc.otm.core.asGetterSetter import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter +import ru.dbotthepony.mc.otm.core.util.computedItem import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatterySlot @@ -48,8 +50,8 @@ class DriveViewerMenu( val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig) val settings = object : DriveViewerBlockEntity.ISettings { - override var sorting: ItemStorageStackSorter by EnumInputWithFeedback(this@DriveViewerMenu, true, tile?.let { it.getSettingsFor(player)::sorting }).also { it.addListener { changes() } } - override var isAscending: Boolean by BooleanInputWithFeedback(this@DriveViewerMenu, true, tile?.let { it.getSettingsFor(player)::isAscending }).also { it.addListener { changes() } } + override var sorting: ItemStorageStackSorter by EnumInputWithFeedback(this@DriveViewerMenu, true, tile?.let { it.getSettingsFor(player)::sorting }).also { it.addListener(::changes) } + override var isAscending: Boolean by BooleanInputWithFeedback(this@DriveViewerMenu, true, tile?.let { it.getSettingsFor(player)::isAscending }).also { it.addListener(::changes) } private fun changes() { if (isAscending) { @@ -73,7 +75,7 @@ class DriveViewerMenu( addInventorySlots() } - var drivePresent by mSynchronizer.bool().property + var drivePresent by mSynchronizer.boolean() private fun getFilter(): ItemFilter? { val stack = (tile as? DriveViewerBlockEntity)?.container?.getItem(0) @@ -81,22 +83,22 @@ class DriveViewerMenu( } val driveFilterSlots = immutableList(PortableCondensationDriveItem.MAX_FILTERS) { i -> - GetterSetter.of( + Delegate.Of( mSynchronizer.computedItem { getFilter()?.get(i) ?: ItemStack.EMPTY }, itemStackInput { getFilter()?.set(i, it) } ) } - private fun make(mapper: (ItemFilter) -> GetterSetter): GetterSetter { - return GetterSetter.of( + private fun make(mapper: (ItemFilter) -> Delegate): Delegate { + return Delegate.Of( { getFilter()?.let(mapper)?.get() ?: false }, { getFilter()?.let(mapper)?.accept(it) } ) } - val isWhitelist = BooleanInputWithFeedback(this, make { it::isWhitelist.asGetterSetter() }).also { it.filter { drivePresent } } - val matchTag = BooleanInputWithFeedback(this, make { it::matchTag.asGetterSetter() }).also { it.filter { drivePresent } } - val matchNBT = BooleanInputWithFeedback(this, make { it::matchNBT.asGetterSetter() }).also { it.filter { drivePresent } } + val isWhitelist = BooleanInputWithFeedback(this, make { Delegate.Of(it::isWhitelist) }).also { it.filter { drivePresent } } + val matchTag = BooleanInputWithFeedback(this, make { Delegate.Of(it::matchTag) }).also { it.filter { drivePresent } } + val matchNBT = BooleanInputWithFeedback(this, make { Delegate.Of(it::matchNBT) }).also { it.filter { drivePresent } } override fun broadcastChanges() { super.broadcastChanges() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/ItemMonitorMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/ItemMonitorMenu.kt index 512424acd..64a2b6208 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/ItemMonitorMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/ItemMonitorMenu.kt @@ -6,6 +6,8 @@ import net.minecraft.world.SimpleContainer import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.item.ItemStack +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.storage.IItemMonitorPlayerSettings import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorBlockEntity import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings @@ -91,8 +93,8 @@ class ItemMonitorMenu( override var ingredientPriority by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::ingredientPriority }) override var resultTarget by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::resultTarget }) override var craftingAmount by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::craftingAmount }) - override var sorting by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::sorting }).also { it.addListener { changes() } } - override var ascendingSort by BooleanInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::ascendingSort }).also { it.addListener { changes() } } + override var sorting by EnumInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::sorting }).also { it.addListener(::changes) } + override var ascendingSort by BooleanInputWithFeedback(this@ItemMonitorMenu, true, tile?.let { it.getSettings(player as ServerPlayer)::ascendingSort }).also { it.addListener(::changes) } private fun changes() { if (ascendingSort) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StoragePowerSupplierMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StoragePowerSupplierMenu.kt index 4e4a2bc00..1d1ab5605 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StoragePowerSupplierMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StoragePowerSupplierMenu.kt @@ -1,7 +1,10 @@ package ru.dbotthepony.mc.otm.menu.storage import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.storage.StoragePowerSupplierBlockEntity +import ru.dbotthepony.mc.otm.core.util.decimal import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.registry.MMenus diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt index 5239bc527..523d7ddd2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ChemicalGeneratorMenu.kt @@ -5,6 +5,8 @@ import net.minecraft.world.entity.player.Inventory import net.minecraft.world.item.ItemStack import net.minecraftforge.common.ForgeHooks import net.minecraftforge.common.capabilities.ForgeCapabilities +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting import ru.dbotthepony.mc.otm.block.entity.tech.ChemicalGeneratorBlockEntity import ru.dbotthepony.mc.otm.core.ifPresentK @@ -54,7 +56,7 @@ class ChemicalGeneratorMenu @JvmOverloads constructor(id: Int, inv: Inventory, t val progress = ProgressGaugeWidget(this) val energy = ProfiledLevelGaugeWidget(this, tile?.energy) - var burnTime by mSynchronizer.int().property + var burnTime by mSynchronizer.int() init { addStorageSlot(fuelSlot) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyCounterMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyCounterMenu.kt index 6d98b6857..b23aafec6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyCounterMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyCounterMenu.kt @@ -4,10 +4,14 @@ import net.minecraft.core.Direction import kotlin.jvm.JvmOverloads import net.minecraft.world.entity.player.Inventory import net.minecraft.world.level.block.Block +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock import ru.dbotthepony.mc.otm.block.entity.tech.EnergyCounterBlockEntity import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.mc.otm.core.math.toDecimal +import ru.dbotthepony.mc.otm.core.util.decimal import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback import ru.dbotthepony.mc.otm.registry.MMenus @@ -22,7 +26,7 @@ class EnergyCounterMenu @JvmOverloads constructor( var average by mSynchronizer.decimal() var last20Ticks by mSynchronizer.decimal() var lastTick by mSynchronizer.decimal() - var maxIO by mSynchronizer.bigDecimal() + var maxIO by mSynchronizer.decimal() val switchDirection = oneWayInput { if (tile is EnergyCounterBlockEntity) @@ -37,14 +41,14 @@ class EnergyCounterMenu @JvmOverloads constructor( } } - var inputDirection by mSynchronizer.enum(Direction::class.java) + var inputDirection: Direction by mSynchronizer.enum(Direction.UP) - val maxIOInput = bigDecimalInput { + val maxIOInput = decimalInput { if (tile is EnergyCounterBlockEntity) { if (it.signum() < 0) { tile.ioLimit = null } else { - tile.ioLimit = Decimal(it) + tile.ioLimit = it } } } @@ -67,7 +71,7 @@ class EnergyCounterMenu @JvmOverloads constructor( ticksPassed = (ticksPassed + 1) % 20 inputDirection = tile.blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION) - maxIO = tile.ioLimit?.toBigDecmial() ?: -BigDecimal.ONE + maxIO = tile.ioLimit?.toDecimal() ?: -Decimal.ONE } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EssenceStorageMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EssenceStorageMenu.kt index 6b92edd50..0c6f2519d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EssenceStorageMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EssenceStorageMenu.kt @@ -5,6 +5,7 @@ import net.minecraft.world.SimpleContainer import net.minecraft.world.entity.player.Inventory import net.minecraft.world.item.ItemStack import net.minecraft.world.item.enchantment.Enchantments +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting import ru.dbotthepony.mc.otm.block.entity.tech.EssenceStorageBlockEntity import ru.dbotthepony.mc.otm.core.util.getTotalXpRequiredForLevel @@ -17,13 +18,14 @@ import ru.dbotthepony.mc.otm.menu.input.FluidConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MMenus +import java.util.function.LongSupplier class EssenceStorageMenu( containerID: Int, inventory: Inventory, tile: EssenceStorageBlockEntity? = null ) : MatteryMenu(MMenus.ESSENCE_STORAGE, containerID, inventory, tile) { - val experienceStored by mSynchronizer.ComputedLongField(getter = { tile?.experienceStored ?: 0L }).property + val experienceStored by mSynchronizer.computedLong(delegate = LongSupplier { tile?.experienceStored ?: 0L }) val redstoneConfig = EnumInputWithFeedback(this) val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig) val fluidConfig = FluidConfigPlayerInput(this, tile?.fluidConfig) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/FluidGaugeWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/FluidGaugeWidget.kt index ca7d3b7cd..a6cde9eb0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/FluidGaugeWidget.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/FluidGaugeWidget.kt @@ -2,21 +2,22 @@ package ru.dbotthepony.mc.otm.menu.widget import net.minecraftforge.fluids.FluidStack import net.minecraftforge.fluids.capability.IFluidHandler +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.core.util.FluidStackValueCodec import ru.dbotthepony.mc.otm.menu.MatteryMenu -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer import java.util.function.IntSupplier import java.util.function.Supplier -class FluidGaugeWidget(synchronizer: FieldSynchronizer) { +class FluidGaugeWidget(synchronizer: DelegateSyncher) { constructor(menu: MatteryMenu) : this(menu.mSynchronizer) var maxCapacitySupplier = IntSupplier { 0 } var fluidSupplier = Supplier { FluidStack.EMPTY!! } - val maxCapacity by synchronizer.ComputedIntField({ maxCapacitySupplier.asInt }) - val fluid by synchronizer.ComputedField({ fluidSupplier.get() }, FluidStackValueCodec) + val maxCapacity by synchronizer.computedInt(IntSupplier { maxCapacitySupplier.asInt }) + val fluid by synchronizer.computed({ fluidSupplier.get() }, FluidStackValueCodec) val percentage: Float get() { if (maxCapacity <= 0 || fluid.isEmpty) { @@ -26,7 +27,7 @@ class FluidGaugeWidget(synchronizer: FieldSynchronizer) { return (fluid.amount.toFloat() / maxCapacity.toFloat()).coerceIn(0f, 1f) } - constructor(synchronizer: FieldSynchronizer, fluid: IFluidHandler?, tank: Int = 0) : this(synchronizer) { + constructor(synchronizer: DelegateSyncher, fluid: IFluidHandler?, tank: Int = 0) : this(synchronizer) { if (fluid != null) { with(fluid, tank) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/LevelGaugeWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/LevelGaugeWidget.kt index eddd1a7ba..3439e0d03 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/LevelGaugeWidget.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/LevelGaugeWidget.kt @@ -1,22 +1,23 @@ package ru.dbotthepony.mc.otm.menu.widget +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec import ru.dbotthepony.mc.otm.menu.MatteryMenu -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer @Suppress("unused") -class LevelGaugeWidget(synchronizer: FieldSynchronizer) { +class LevelGaugeWidget(synchronizer: DelegateSyncher) { constructor(menu: MatteryMenu) : this(menu.mSynchronizer) var levelProvider = { Decimal.ONE } var maxLevelProvider = { Decimal.ONE } - val level by synchronizer.ComputedField(getter = { levelProvider.invoke() }, codec = DecimalValueCodec) - val maxLevel by synchronizer.ComputedField(getter = { maxLevelProvider.invoke() }, codec = DecimalValueCodec) + val level by synchronizer.computed(delegate = { levelProvider.invoke() }, codec = DecimalValueCodec) + val maxLevel by synchronizer.computed(delegate = { maxLevelProvider.invoke() }, codec = DecimalValueCodec) constructor( menu: MatteryMenu, @@ -55,7 +56,7 @@ class LevelGaugeWidget(synchronizer: FieldSynchronizer) { } constructor( - synchronizer: FieldSynchronizer, + synchronizer: DelegateSyncher, power: IMatteryEnergyStorage? ) : this(synchronizer) { if (power != null) { @@ -64,7 +65,7 @@ class LevelGaugeWidget(synchronizer: FieldSynchronizer) { } constructor( - synchronizer: FieldSynchronizer, + synchronizer: DelegateSyncher, matter: IMatterStorage? ) : this(synchronizer) { if (matter != null) { @@ -73,7 +74,7 @@ class LevelGaugeWidget(synchronizer: FieldSynchronizer) { } constructor( - synchronizer: FieldSynchronizer, + synchronizer: DelegateSyncher, patterns: IPatternStorage? ) : this(synchronizer) { if (patterns != null) { @@ -82,7 +83,7 @@ class LevelGaugeWidget(synchronizer: FieldSynchronizer) { } constructor( - synchronizer: FieldSynchronizer, + synchronizer: DelegateSyncher, level: () -> Decimal, maxLevel: () -> Decimal, ) : this(synchronizer) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledLevelGaugeWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledLevelGaugeWidget.kt index 486168417..8261cea21 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledLevelGaugeWidget.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProfiledLevelGaugeWidget.kt @@ -1,5 +1,7 @@ package ru.dbotthepony.mc.otm.menu.widget +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage @@ -9,28 +11,28 @@ import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer +import java.util.function.IntSupplier -class ProfiledLevelGaugeWidget

>(synchronizer: FieldSynchronizer, val gauge: LevelGaugeWidget = LevelGaugeWidget(synchronizer)) { +class ProfiledLevelGaugeWidget

>(synchronizer: DelegateSyncher, val gauge: LevelGaugeWidget = LevelGaugeWidget(synchronizer)) { var parent: P? = null private set val historyReceive = immutableList(AbstractProfiledStorage.HISTORY_SIZE) { - synchronizer.ComputedField({ parent?.historyReceive?.get(it) ?: Decimal.ZERO }, DecimalValueCodec) + synchronizer.computed({ parent?.historyReceive?.get(it) ?: Decimal.ZERO }, DecimalValueCodec) } val historyTransfer = immutableList(AbstractProfiledStorage.HISTORY_SIZE) { - synchronizer.ComputedField({ parent?.historyTransfer?.get(it) ?: Decimal.ZERO }, DecimalValueCodec) + synchronizer.computed({ parent?.historyTransfer?.get(it) ?: Decimal.ZERO }, DecimalValueCodec) } val directHistoryReceive = SupplierList(historyReceive) val directHistoryTransfer = SupplierList(historyTransfer) - val tick by synchronizer.ComputedIntField({ parent?.tick ?: 0 }).property - val lastTickReceive by synchronizer.ComputedField({ parent?.lastTickReceive ?: Decimal.ZERO }, DecimalValueCodec) - val lastTickTransfer by synchronizer.ComputedField({ parent?.lastTickTransfer ?: Decimal.ZERO }, DecimalValueCodec) + val tick by synchronizer.computedInt(IntSupplier { parent?.tick ?: 0 }) + val lastTickReceive by synchronizer.computed({ parent?.lastTickReceive ?: Decimal.ZERO }, DecimalValueCodec) + val lastTickTransfer by synchronizer.computed({ parent?.lastTickTransfer ?: Decimal.ZERO }, DecimalValueCodec) - constructor(synchronizer: FieldSynchronizer, storage: P?, gauge: LevelGaugeWidget = LevelGaugeWidget(synchronizer)) : this(synchronizer, gauge = gauge) { + constructor(synchronizer: DelegateSyncher, storage: P?, gauge: LevelGaugeWidget = LevelGaugeWidget(synchronizer)) : this(synchronizer, gauge = gauge) { if (storage != null) { with(storage) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProgressGaugeWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProgressGaugeWidget.kt index 6ca06cff3..91ebc2df0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProgressGaugeWidget.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/ProgressGaugeWidget.kt @@ -1,21 +1,22 @@ package ru.dbotthepony.mc.otm.menu.widget +import ru.dbotthepony.kommons.io.DelegateSyncher +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.block.entity.MachineJobEventLoop import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity import ru.dbotthepony.mc.otm.core.FloatSupplier import ru.dbotthepony.mc.otm.menu.MatteryMenu -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer import java.util.function.BooleanSupplier @Suppress("unused") -class ProgressGaugeWidget(synchronizer: FieldSynchronizer) { +class ProgressGaugeWidget(synchronizer: DelegateSyncher) { constructor(menu: MatteryMenu) : this(menu.mSynchronizer) var progressSupplier: FloatSupplier = FloatSupplier { 0f } var stuckSupplier: BooleanSupplier = BooleanSupplier { false } - val percentage by synchronizer.ComputedFloatField(getter = { progressSupplier.getAsFloat() }).property - val isStuck by synchronizer.ComputedBooleanField(getter = { stuckSupplier.asBoolean }).property + val percentage by synchronizer.computedFloat(delegate = { progressSupplier.getAsFloat() }) + val isStuck by synchronizer.computedBoolean(delegate = BooleanSupplier { stuckSupplier.asBoolean }) constructor( menu: MatteryMenu, @@ -43,14 +44,14 @@ class ProgressGaugeWidget(synchronizer: FieldSynchronizer) { } constructor( - synchronizer: FieldSynchronizer, + synchronizer: DelegateSyncher, progress: FloatSupplier ) : this(synchronizer) { this.progressSupplier = progress } constructor( - synchronizer: FieldSynchronizer, + synchronizer: DelegateSyncher, blockEntity: MatteryWorkerBlockEntity<*>? ) : this(synchronizer) { if (blockEntity != null) { @@ -59,7 +60,7 @@ class ProgressGaugeWidget(synchronizer: FieldSynchronizer) { } constructor( - synchronizer: FieldSynchronizer, + synchronizer: DelegateSyncher, job: MachineJobEventLoop<*>? ) : this(synchronizer) { if (job != null) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/GenericNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/GenericNetworkChannel.kt index a685e0d0e..9d3c19820 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/GenericNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/GenericNetworkChannel.kt @@ -90,11 +90,11 @@ class BlockEntitySyncPacket(val position: BlockPos, val buffer: ByteArray, val v LOGGER.info("Unfolding ${packets.size} backlog packets for $position (${level.getBlockState(position)}/$blockEntity)") for (packet in packets) { - blockEntity.synchronizer.read(FastByteArrayInputStream(packet)) + blockEntity.syncher.read(FastByteArrayInputStream(packet)) } } - blockEntity.synchronizer.read(FastByteArrayInputStream(buffer, 0, validBytes)) + blockEntity.syncher.read(FastByteArrayInputStream(buffer, 0, validBytes)) } catch(err: Throwable) { LOGGER.error("Exception while reading synchronized BlockEntity data!\nPosition: $position\nBlock: ${level.getBlockState(position)}\nBlock entity: $blockEntity", err) } @@ -125,7 +125,7 @@ class BlockEntitySyncPacket(val position: BlockPos, val buffer: ByteArray, val v LOGGER.info("Unfolding ${packets.size} backlog packets (size: ${packets.iterator().map { it.size }.reduce(0, Int::plus)} bytes) for ${blockEntity.blockPos} (${blockEntity.level!!.getBlockState(blockEntity.blockPos)}/$blockEntity)") for (packet in packets) { - blockEntity.synchronizer.read(FastByteArrayInputStream(packet)) + blockEntity.syncher.read(FastByteArrayInputStream(packet)) } } } catch(err: Throwable) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryNetworkChannel.kt index ff1e4cf11..948084ea0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryNetworkChannel.kt @@ -12,9 +12,11 @@ import net.minecraftforge.network.NetworkDirection import net.minecraftforge.network.PacketDistributor import net.minecraftforge.network.SimpleChannel import org.apache.logging.log4j.LogManager +import ru.dbotthepony.kommons.util.Delegate +import ru.dbotthepony.kommons.util.getValue +import ru.dbotthepony.kommons.util.setValue import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER import ru.dbotthepony.mc.otm.OverdriveThatMatters -import ru.dbotthepony.mc.otm.core.GetterSetter import java.util.concurrent.CompletableFuture import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.locks.LockSupport @@ -22,7 +24,7 @@ import java.util.function.BiConsumer import java.util.function.Function import kotlin.reflect.KClass -class MNetworkContext(val sender: ServerPlayer?, packetHandled: GetterSetter, private val enqueuer: (Runnable) -> CompletableFuture<*>) { +class MNetworkContext(val sender: ServerPlayer?, packetHandled: Delegate, private val enqueuer: (Runnable) -> CompletableFuture<*>) { var packetHandled by packetHandled fun enqueueWork(callback: Runnable): CompletableFuture<*> { @@ -96,7 +98,7 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) { } val builder = channel.messageBuilder(packetClass, direction) - val bridgeHandler = BiConsumer { a, b -> handler(a, MNetworkContext(b.sender, GetterSetter.of({ b.packetHandled }, { b.packetHandled = it }), b::enqueueWork)) } + val bridgeHandler = BiConsumer { a, b -> handler(a, MNetworkContext(b.sender, Delegate.Of({ b.packetHandled }, { b.packetHandled = it }), b::enqueueWork)) } if (handleOnMainThread) { builder.consumerMainThread(bridgeHandler) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt index de0d36f7c..42b9e281f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt @@ -26,7 +26,7 @@ import ru.dbotthepony.mc.otm.client.render.GlitchRenderer import ru.dbotthepony.mc.otm.client.render.ShockwaveRenderer import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.container.set -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.math.component1 import ru.dbotthepony.mc.otm.core.math.component2 @@ -63,9 +63,9 @@ class MatteryPlayerFieldPacket(val bytes: ByteArray, val length: Int, val isPubl } if (isPublic) { - player.publicSynchronizer.read(ByteArrayInputStream(bytes, 0, length)) + player.publicSyncher.read(ByteArrayInputStream(bytes, 0, length)) } else { - player.synchronizer.read(ByteArrayInputStream(bytes, 0, length)) + player.syncher.read(ByteArrayInputStream(bytes, 0, length)) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/ChangesetAction.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/ChangesetAction.kt deleted file mode 100644 index 870e44ea7..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/ChangesetAction.kt +++ /dev/null @@ -1,5 +0,0 @@ -package ru.dbotthepony.mc.otm.network.synchronizer - -enum class ChangesetAction { - CLEAR, ADD, REMOVE -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldAccess.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldAccess.kt deleted file mode 100644 index c43201a31..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldAccess.kt +++ /dev/null @@ -1,41 +0,0 @@ -package ru.dbotthepony.mc.otm.network.synchronizer - -interface FieldAccess { - fun read(): V - fun write(value: V) -} - -interface FloatFieldAccess : FieldAccess { - override fun write(value: Float) - @Deprecated("Use type specific method", replaceWith = ReplaceWith("this.readFloat()")) - override fun read() = readFloat() - fun readFloat(): Float -} - -interface DoubleFieldAccess : FieldAccess { - override fun write(value: Double) - @Deprecated("Use type specific method", replaceWith = ReplaceWith("this.readDouble()")) - override fun read() = readDouble() - fun readDouble(): Double -} - -interface IntFieldAccess : FieldAccess { - override fun write(value: Int) - @Deprecated("Use type specific method", replaceWith = ReplaceWith("this.readInt()")) - override fun read() = readInt() - fun readInt(): Int -} - -interface LongFieldAccess : FieldAccess { - override fun write(value: Long) - @Deprecated("Use type specific method", replaceWith = ReplaceWith("this.readLong()")) - override fun read() = readLong() - fun readLong(): Long -} - -interface BooleanFieldAccess : FieldAccess { - override fun write(value: Boolean) - @Deprecated("Use type specific method", replaceWith = ReplaceWith("this.readBoolean()")) - override fun read() = readBoolean() - fun readBoolean(): Boolean -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldGetter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldGetter.kt deleted file mode 100644 index 4389e1ca3..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldGetter.kt +++ /dev/null @@ -1,50 +0,0 @@ -package ru.dbotthepony.mc.otm.network.synchronizer - -fun interface FieldGetter { - fun invoke(field: FieldAccess): V -} - -fun interface FloatFieldGetter : FieldGetter { - fun invoke(field: FloatFieldAccess): Float - - @Deprecated("Use type specific invoke") - override fun invoke(field: FieldAccess): Float { - return invoke(field as FloatFieldAccess) - } -} - -fun interface DoubleFieldGetter : FieldGetter { - fun invoke(field: DoubleFieldAccess): Double - - @Deprecated("Use type specific invoke") - override fun invoke(field: FieldAccess): Double { - return invoke(field as DoubleFieldAccess) - } -} - -fun interface IntFieldGetter : FieldGetter { - fun invoke(field: IntFieldAccess): Int - - @Deprecated("Use type specific invoke") - override fun invoke(field: FieldAccess): Int { - return invoke(field as IntFieldAccess) - } -} - -fun interface LongFieldGetter : FieldGetter { - fun invoke(field: LongFieldAccess): Long - - @Deprecated("Use type specific invoke") - override fun invoke(field: FieldAccess): Long { - return invoke(field as LongFieldAccess) - } -} - -fun interface BooleanFieldGetter : FieldGetter { - fun invoke(field: BooleanFieldAccess): Boolean - - @Deprecated("Use type specific invoke") - override fun invoke(field: FieldAccess): Boolean { - return invoke(field as BooleanFieldAccess) - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSetter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSetter.kt deleted file mode 100644 index 3a5e4fb40..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSetter.kt +++ /dev/null @@ -1,50 +0,0 @@ -package ru.dbotthepony.mc.otm.network.synchronizer - -fun interface FieldSetter { - fun invoke(value: V, access: FieldAccess, setByRemote: Boolean) -} - -fun interface FloatFieldSetter : FieldSetter { - fun invoke(value: Float, access: FloatFieldAccess, setByRemote: Boolean) - - @Deprecated("Use type specific invoke") - override fun invoke(value: Float, access: FieldAccess, setByRemote: Boolean) { - invoke(value, access as FloatFieldAccess, setByRemote) - } -} - -fun interface DoubleFieldSetter : FieldSetter { - fun invoke(value: Double, access: DoubleFieldAccess, setByRemote: Boolean) - - @Deprecated("Use type specific invoke") - override fun invoke(value: Double, access: FieldAccess, setByRemote: Boolean) { - invoke(value, access as DoubleFieldAccess, setByRemote) - } -} - -fun interface IntFieldSetter : FieldSetter { - fun invoke(value: Int, access: IntFieldAccess, setByRemote: Boolean) - - @Deprecated("Use type specific invoke") - override fun invoke(value: Int, access: FieldAccess, setByRemote: Boolean) { - invoke(value, access as IntFieldAccess, setByRemote) - } -} - -fun interface LongFieldSetter : FieldSetter { - fun invoke(value: Long, access: LongFieldAccess, setByRemote: Boolean) - - @Deprecated("Use type specific invoke") - override fun invoke(value: Long, access: FieldAccess, setByRemote: Boolean) { - invoke(value, access as LongFieldAccess, setByRemote) - } -} - -fun interface BooleanFieldSetter : FieldSetter { - fun invoke(value: Boolean, access: BooleanFieldAccess, setByRemote: Boolean) - - @Deprecated("Use type specific invoke") - override fun invoke(value: Boolean, access: FieldAccess, setByRemote: Boolean) { - invoke(value, access as BooleanFieldAccess, setByRemote) - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt deleted file mode 100644 index c9dd51db8..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt +++ /dev/null @@ -1,2190 +0,0 @@ -@file:Suppress("DeprecatedCallableAddReplaceWith") - -package ru.dbotthepony.mc.otm.network.synchronizer - -import it.unimi.dsi.fastutil.booleans.BooleanConsumer -import it.unimi.dsi.fastutil.floats.FloatConsumer -import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream -import it.unimi.dsi.fastutil.objects.Reference2ObjectFunction -import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap -import it.unimi.dsi.fastutil.objects.ReferenceArraySet -import net.minecraft.world.item.ItemStack -import ru.dbotthepony.mc.otm.core.* -import ru.dbotthepony.mc.otm.core.collect.ProxiedMap -import ru.dbotthepony.mc.otm.core.math.Decimal -import ru.dbotthepony.mc.otm.core.util.BigDecimalValueCodec -import ru.dbotthepony.mc.otm.core.util.BinaryStringCodec -import ru.dbotthepony.mc.otm.core.util.ByteValueCodec -import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec -import ru.dbotthepony.mc.otm.core.util.EnumValueCodec -import ru.dbotthepony.mc.otm.core.util.IStreamCodec -import ru.dbotthepony.mc.otm.core.util.ItemStackValueCodec -import ru.dbotthepony.mc.otm.core.util.ShortValueCodec -import ru.dbotthepony.mc.otm.core.util.UUIDValueCodec -import ru.dbotthepony.mc.otm.core.util.readVarIntLE -import ru.dbotthepony.mc.otm.core.util.readVarLongLE -import ru.dbotthepony.mc.otm.core.util.writeVarIntLE -import ru.dbotthepony.mc.otm.core.util.writeVarLongLE -import ru.dbotthepony.mc.otm.secondTime -import java.io.DataInputStream -import java.io.DataOutputStream -import java.io.InputStream -import java.lang.ref.WeakReference -import java.math.BigDecimal -import java.util.* -import java.util.function.BooleanSupplier -import java.util.function.Consumer -import java.util.function.DoubleConsumer -import java.util.function.DoubleSupplier -import java.util.function.IntConsumer -import java.util.function.IntSupplier -import java.util.function.LongConsumer -import java.util.function.LongSupplier -import java.util.function.Supplier -import kotlin.reflect.KMutableProperty0 -import kotlin.reflect.KProperty -import kotlin.reflect.KProperty0 - -/** - * Universal, one-to-many value synchronizer, allowing to synchronize values from server to client - * anywhere, where input/output streams are supported - */ -@Suppress("unused", "BlockingMethodInNonBlockingContext") -class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCallback: Boolean) { - constructor() : this(Runnable {}, false) - constructor(callback: Runnable) : this(callback, false) - - private var freeSlots = 0 - // почему не удалять поля напрямую? - // чтоб не возникло проблем в состоянии гонки - // формируем пакет -> удаляем поле по обе стороны -> клиент принимает пакет -> клиент считывает неверные данные - // конечно, всё равно всё сломается если было удалено поле, которое находится в пакете - // но если поля нет в пакете, то всё окей - private val fields = ArrayList?>(0) - private val observers = ArrayList>(0) - - private var nextFieldID = 0 - - val hasObservers: Boolean get() = observers.isNotEmpty() - - var isEmpty: Boolean = true - private set - - val isNotEmpty: Boolean get() = !isEmpty - - var isDirty: Boolean = false - private set(value) { - if (value != field) { - field = value - - if (value && !alwaysCallCallback) { - callback.run() - } - } - - if (alwaysCallCallback && value) { - callback.run() - } - } - - fun markClean() { - isDirty = false - } - - fun computedByte(getter: () -> Byte) = ComputedField(getter, ByteValueCodec) - fun computedBool(getter: BooleanSupplier) = ComputedBooleanField(getter) - fun computedShort(getter: () -> Short) = ComputedField(getter, ShortValueCodec) - fun computedLong(getter: LongSupplier) = ComputedLongField(getter) - fun computedFixedLong(getter: LongSupplier) = ComputedFixedLongField(getter) - fun computedFloat(getter: FloatSupplier) = ComputedFloatField(getter) - fun computedDouble(getter: DoubleSupplier) = ComputedDoubleField(getter) - fun computedUuid(getter: () -> UUID) = ComputedField(getter, UUIDValueCodec) - fun computedInt(getter: IntSupplier) = ComputedIntField(getter) - fun computedFixedInt(getter: IntSupplier) = ComputedFixedIntField(getter) - fun computedDecimal(getter: () -> Decimal) = ComputedField(getter, DecimalValueCodec) - fun computedBigDecimal(getter: () -> BigDecimal) = ComputedField(getter, BigDecimalValueCodec) - fun computedItem(getter: () -> ItemStack) = ComputedField(getter, ItemStackValueCodec) - fun computedString(getter: () -> String) = ComputedField(getter, BinaryStringCodec) - - fun computedByte(getter: KProperty0) = ComputedField(getter, ByteValueCodec) - fun computedBool(getter: KProperty0) = ComputedBooleanField(getter::get) - fun computedShort(getter: KProperty0) = ComputedField(getter, ShortValueCodec) - fun computedLong(getter: KProperty0) = ComputedLongField(getter::get) - fun computedFixedLong(getter: KProperty0) = ComputedFixedLongField(getter::get) - fun computedFloat(getter: KProperty0) = ComputedFloatField(getter::get) - fun computedDouble(getter: KProperty0) = ComputedDoubleField(getter::get) - fun computedUuid(getter: KProperty0) = ComputedField(getter, UUIDValueCodec) - fun computedInt(getter: KProperty0) = ComputedIntField(getter::get) - fun computedFixedInt(getter: KProperty0) = ComputedFixedIntField(getter::get) - fun computedDecimal(getter: KProperty0) = ComputedField(getter, DecimalValueCodec) - fun computedBigDecimal(getter: KProperty0) = ComputedField(getter, BigDecimalValueCodec) - fun computedItem(getter: KProperty0) = ComputedField(getter, ItemStackValueCodec) - fun computedString(getter: KProperty0) = ComputedField(getter, BinaryStringCodec) - - fun computedByte(getter: Supplier) = ComputedField(getter::get, ByteValueCodec) - fun computedBool(getter: Supplier) = ComputedBooleanField(getter::get) - fun computedShort(getter: Supplier) = ComputedField(getter::get, ShortValueCodec) - fun computedLong(getter: Supplier) = ComputedLongField(getter::get) - fun computedFixedLong(getter: Supplier) = ComputedFixedLongField(getter::get) - fun computedFloat(getter: Supplier) = ComputedFloatField(getter::get) - fun computedDouble(getter: Supplier) = ComputedDoubleField(getter::get) - fun computedUuid(getter: Supplier) = ComputedField(getter::get, UUIDValueCodec) - fun computedInt(getter: Supplier) = ComputedIntField(getter::get) - fun computedFixedInt(getter: Supplier) = ComputedFixedIntField(getter::get) - fun computedDecimal(getter: Supplier) = ComputedField(getter::get, DecimalValueCodec) - fun computedBigDecimal(getter: Supplier) = ComputedField(getter::get, BigDecimalValueCodec) - fun computedItem(getter: Supplier) = ComputedField(getter::get, ItemStackValueCodec) - fun computedString(getter: Supplier) = ComputedField(getter::get, BinaryStringCodec) - - fun > computedEnum(type: Class, getter: () -> T) = ComputedField(getter, EnumValueCodec(type)) - inline fun > computedEnum(noinline getter: () -> T) = ComputedField(getter, EnumValueCodec(T::class.java)) - - fun > computedEnum(type: Class, getter: KProperty0) = ComputedField(getter, EnumValueCodec(type)) - inline fun > computedEnum(getter: KProperty0) = ComputedField(getter, EnumValueCodec(T::class.java)) - - fun > computedEnum(type: Class, getter: Supplier) = ComputedField(getter::get, EnumValueCodec(type)) - inline fun > computedEnum(getter: Supplier) = ComputedField(getter::get, EnumValueCodec(T::class.java)) - - @JvmOverloads - fun byte( - value: Byte = 0, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - ): Field { - return Field(value, ByteValueCodec, getter, setter) - } - - @JvmOverloads - fun bool( - value: Boolean = false, - getter: BooleanFieldGetter? = null, - setter: BooleanFieldSetter? = null, - ): BooleanField { - return BooleanField(value, getter, setter) - } - - @JvmOverloads - fun short( - value: Short = 0, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - ): Field { - return Field(value, ShortValueCodec, getter, setter) - } - - @JvmOverloads - fun long( - value: Long = 0L, - getter: LongFieldGetter? = null, - setter: LongFieldSetter? = null, - ): LongField { - return LongField(value, getter, setter) - } - - @JvmOverloads - fun fixedLong( - value: Long = 0L, - getter: LongFieldGetter? = null, - setter: LongFieldSetter? = null, - ): FixedLongField { - return FixedLongField(value, getter, setter) - } - - @JvmOverloads - fun float( - value: Float = 0f, - getter: FloatFieldGetter? = null, - setter: FloatFieldSetter? = null, - ): FloatField { - return FloatField(value, getter, setter) - } - - @JvmOverloads - fun double( - value: Double = 0.0, - getter: DoubleFieldGetter? = null, - setter: DoubleFieldSetter? = null, - ): DoubleField { - return DoubleField(value, getter, setter) - } - - @JvmOverloads - fun uuid( - value: UUID = UUID(0L, 0L), - getter: FieldGetter? = null, - setter: FieldSetter? = null, - ): Field { - return Field(value, UUIDValueCodec, getter, setter) - } - - @JvmOverloads - fun int( - value: Int = 0, - getter: IntFieldGetter? = null, - setter: IntFieldSetter? = null, - ): IntField { - return IntField(value, getter, setter) - } - - @JvmOverloads - fun string( - value: String = "", - getter: FieldGetter? = null, - setter: FieldSetter? = null, - ): Field { - return Field(value, BinaryStringCodec, getter, setter) - } - - @JvmOverloads - fun fixedInt( - value: Int = 0, - getter: IntFieldGetter? = null, - setter: IntFieldSetter? = null, - ): FixedIntField { - return FixedIntField(value, getter, setter) - } - - @JvmOverloads - fun decimal( - value: Decimal = Decimal.ZERO, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - ): Field { - return Field(value, DecimalValueCodec, getter, setter) - } - - @JvmOverloads - fun bigDecimal( - value: BigDecimal = BigDecimal.ZERO, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - ): Field { - return Field(value, BigDecimalValueCodec, getter, setter) - } - - @JvmOverloads - fun > enum( - type: Class, - value: T = type.enumConstants[0], - getter: FieldGetter? = null, - setter: FieldSetter? = null, - ): Field { - return Field(value, EnumValueCodec(type), getter, setter) - } - - @JvmOverloads - fun > enum( - value: T, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - ): Field { - return Field(value, EnumValueCodec(value::class.java), getter, setter) - } - - @JvmOverloads - fun item( - value: ItemStack = ItemStack.EMPTY, - getter: FieldGetter? = null, - setter: FieldSetter? = null, - observe: Boolean = true, - ): Field { - return Field(value, ItemStackValueCodec, getter, setter, isObserver = observe) - } - - fun item( - delegate: KMutableProperty0, - ): ObservedField { - return ObservedField(delegate, ItemStackValueCodec) - } - - private var endpointsMaxCapacity = 1 - private val endpoints = ArrayList>(1) - val defaultEndpoint = Endpoint() - - private var nextEndpointsCleanup = secondTime - - private fun notifyEndpoints(dirtyField: AbstractField<*>) { - isDirty = true - - forEachEndpoint { - it.addDirtyField(dirtyField) - } - } - - private inline fun forEachEndpoint(execute: (Endpoint) -> Unit) { - nextEndpointsCleanup = secondTime + 60 - - synchronized(endpoints) { - endpoints.forValidRefs { execute.invoke(it) } - - if (endpoints.size < endpointsMaxCapacity / 2) { - endpoints.trimToSize() - endpointsMaxCapacity = endpoints.size - } - } - } - - inner class Endpoint { - init { - synchronized(endpoints) { - endpoints.add(WeakReference(this)) - endpointsMaxCapacity = endpointsMaxCapacity.coerceAtLeast(endpoints.size) - - if (secondTime >= nextEndpointsCleanup) { - nextEndpointsCleanup = secondTime + 60 - - val iterator = endpoints.listIterator() - - for (value in iterator) { - if (value.get() == null) { - iterator.remove() - } - } - - if (endpoints.size < endpointsMaxCapacity / 2) { - endpoints.trimToSize() - endpointsMaxCapacity = endpoints.size - } - } - } - } - - private val dirtyFields = ReferenceArraySet>(4) - - // use LinkedList because it is ensured memory is freed on LinkedList#clear - private val mapBacklogs = Reference2ObjectOpenHashMap, LinkedList Unit>>>() - private val setBacklogs = Reference2ObjectOpenHashMap, LinkedList Unit>>>() - - var unused: Boolean = false - private set - - fun markUnused() { - require(this === defaultEndpoint) { "This is not a default endpoint" } - if (unused) return - unused = true - mapBacklogs.clear() - dirtyFields.clear() - - val iterator = endpoints.listIterator() - - for (value in iterator) { - if (value.get() === this) { - iterator.remove() - } - } - } - - init { - markDirty() - } - - fun markDirty() { - for (field in fields) { - field?.markDirty(this) - } - } - - internal fun addDirtyField(field: AbstractField<*>) { - if (unused) { - return - } - - dirtyFields.add(field) - } - - internal fun removeDirtyField(field: AbstractField<*>) { - dirtyFields.remove(field) - } - - internal fun getMapBacklog(map: Map): LinkedList Unit>> { - if (unused) { - return LinkedList() - } - - return mapBacklogs.computeIfAbsent(map, Reference2ObjectFunction { - LinkedList() - }) - } - - internal fun removeMapBacklog(map: Map) { - mapBacklogs.remove(map) - } - - internal fun getSetBacklog(set: Set): LinkedList Unit>> { - if (unused) { - return LinkedList() - } - - return setBacklogs.computeIfAbsent(set, Reference2ObjectFunction { - LinkedList() - }) - } - - internal fun removeSetBacklog(set: Set) { - setBacklogs.remove(set) - } - - fun collectNetworkPayload(): FastByteArrayOutputStream? { - if (unused || dirtyFields.isEmpty()) { - return null - } - - val stream = FastByteArrayOutputStream() - val dataStream = DataOutputStream(stream) - - for (field in dirtyFields) { - stream.writeVarIntLE(field.id) - field.write(dataStream, this) - } - - dirtyFields.clear() - stream.write(0) - - return stream - } - } - - private val boundEndpoints = WeakHashMap() - - fun computeEndpointFor(obj: Any): Endpoint { - return boundEndpoints.computeIfAbsent(obj) { Endpoint() } - } - - fun removeEndpointFor(obj: Any): Endpoint? { - return boundEndpoints.remove(obj) - } - - fun endpointFor(obj: Any): Endpoint? { - return boundEndpoints[obj] - } - - @Suppress("LeakingThis") - abstract inner class AbstractField : IField { - val id: Int - - init { - if (freeSlots > 0) { - var found = -1 - - for (i in fields.indices) { - if (fields[i] == null) { - fields[i] = this - found = i + 1 - freeSlots-- - break - } - } - - if (found == -1) { - throw RuntimeException("freeSlots = $freeSlots but no null entries in field list!") - } else { - id = found - } - } else { - fields.add(this) - id = fields.size - isEmpty = false - } - } - - final override var isRemoved = false - private set - - protected var isDirty = false - - override fun remove() { - if (isRemoved) - return - - isRemoved = true - freeSlots++ - fields[id - 1] = null - observers.remove(this) - isEmpty = fields.all { it == null } - - while (fields[fields.size - 1] == null) { - fields.removeAt(fields.size - 1) - freeSlots-- - } - - forEachEndpoint { - it.removeDirtyField(this) - } - } - - override fun markDirty(endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - endpoint.addDirtyField(this) - } - - override fun markDirty() { - check(!isRemoved) { "Field was removed" } - notifyEndpoints(this@AbstractField) - isDirty = true - } - } - - /** - * Networked variable with backing field holding immutable value - */ - inner class Field( - private var field: V, - private val codec: IStreamCodec, - private val getter: FieldGetter? = null, - private val setter: FieldSetter? = null, - isObserver: Boolean = false, - ) : AbstractField(), IMutableField { - private var remote: V = codec.copy(field) - private val subs = ISubscriptable.Impl() - - override fun addListener(listener: Consumer): ISubscriptable.L { - return subs.addListener(listener) - } - - init { - if (isObserver) { - observers.add(this) - } - } - - private val access = object : FieldAccess { - override fun read(): V { - return field - } - - override fun write(value: V) { - if (!isDirty && !codec.compare(remote, value)) { - notifyEndpoints(this@Field) - isDirty = true - } - - this@Field.field = value - subs.accept(value) - } - } - - override fun observe(): Boolean { - check(!isRemoved) { "Field was removed" } - - if (!isDirty && !codec.compare(remote, field)) { - notifyEndpoints(this@Field) - isDirty = true - } - - return isDirty - } - - override var value: V - get() { - val getter = this.getter - - if (getter != null) { - return getter.invoke(access) - } - - return this.field - } - set(value) { - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, false) - } else { - if (!isDirty && !codec.compare(remote, value)) { - notifyEndpoints(this@Field) - isDirty = true - } - - this.field = value - subs.accept(value) - } - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - codec.write(stream, field) - isDirty = false - remote = codec.copy(field) - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val value = codec.read(stream) - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, true) - } else { - this.field = value - subs.accept(value) - } - } - } - - abstract inner class PrimitiveField : AbstractField() { - override fun observe(): Boolean { - check(!isRemoved) { "Field was removed" } - return isDirty - } - } - - /** - * Type specific field, storing primitive [Float] directly - */ - inner class FloatField(field: Float, private val getter: FloatFieldGetter? = null, private val setter: FloatFieldSetter? = null) : PrimitiveField(), IMutableFloatField { - private val subs = IFloatSubcripable.Impl() - - override fun addListener(listener: FloatConsumer): ISubscriptable.L { - return subs.addListener(listener) - } - - private var field = field - set(value) { - if (field != value) { - field = value - subs.accept(value) - } - } - - override val property = object : IMutableFloatProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): Float { - return this@FloatField.float - } - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Float) { - this@FloatField.float = value - } - } - - private val access = object : FloatFieldAccess { - override fun readFloat(): Float { - return this@FloatField.field - } - - override fun write(value: Float) { - if (!isDirty && value != this@FloatField.field) { - notifyEndpoints(this@FloatField) - isDirty = true - } - - this@FloatField.field = value - } - } - - override var float: Float - get() { - return getter?.invoke(access) ?: this.field - } - set(value) { - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, false) - } else if (value != this.field) { - if (!isDirty) { - notifyEndpoints(this) - isDirty = true - } - - this.field = value - } - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeFloat(this.field) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val value = stream.readFloat() - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, true) - } else { - this.field = value - } - } - } - - /** - * Type specific field, storing primitive [Double] directly - */ - inner class DoubleField(field: Double, private val getter: DoubleFieldGetter? = null, private val setter: DoubleFieldSetter? = null) : PrimitiveField(), IMutableDoubleField { - private val subs = IDoubleSubcripable.Impl() - - override fun addListener(listener: DoubleConsumer): ISubscriptable.L { - return subs.addListener(listener) - } - - private var field = field - set(value) { - if (field != value) { - field = value - subs.accept(value) - } - } - - override val property = object : IMutableDoubleProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): Double { - return this@DoubleField.double - } - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) { - this@DoubleField.double = value - } - } - - private val access = object : DoubleFieldAccess { - override fun readDouble(): Double { - return this@DoubleField.field - } - - override fun write(value: Double) { - if (!isDirty && value != this@DoubleField.field) { - notifyEndpoints(this@DoubleField) - isDirty = true - } - - this@DoubleField.field = value - } - } - - override var double: Double - get() { - return getter?.invoke(access) ?: this.field - } - set(value) { - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, false) - } else if (value != this.field) { - if (!isDirty) { - notifyEndpoints(this) - isDirty = true - } - - this.field = value - } - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeDouble(this.field) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val value = stream.readDouble() - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, true) - } else { - this.field = value - } - } - } - - abstract inner class AbstractIntField(field: Int, private val getter: IntFieldGetter? = null, protected val setter: IntFieldSetter? = null) : PrimitiveField(), IMutableIntField { - private val subs = IIntSubcripable.Impl() - - override fun addListener(listener: IntConsumer): ISubscriptable.L { - return subs.addListener(listener) - } - - protected var field = field - set(value) { - if (field != value) { - field = value - subs.accept(value) - } - } - - final override val property = object : IMutableIntProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): Int { - return this@AbstractIntField.int - } - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { - this@AbstractIntField.int = value - } - } - - protected val access = object : IntFieldAccess { - override fun readInt(): Int { - return this@AbstractIntField.field - } - - override fun write(value: Int) { - if (!isDirty && value != this@AbstractIntField.field) { - notifyEndpoints(this@AbstractIntField) - isDirty = true - } - - this@AbstractIntField.field = value - } - } - - final override var int: Int - get() { - return getter?.invoke(access) ?: this.field - } - set(value) { - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, false) - } else if (value != this.field) { - if (!isDirty) { - notifyEndpoints(this) - isDirty = true - } - - this.field = value - } - } - } - - /** - * Type specific field, storing primitive [Int] directly, and networking it as variable length integer - */ - inner class IntField(field: Int, getter: IntFieldGetter? = null, setter: IntFieldSetter? = null) : AbstractIntField(field, getter, setter) { - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeVarIntLE(this.field) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val value = stream.readVarIntLE() - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, true) - } else { - this.field = value - } - } - } - - /** - * Type specific field, storing primitive [Int] directly, and networking it as 4 octets - */ - inner class FixedIntField(field: Int, getter: IntFieldGetter? = null, setter: IntFieldSetter? = null) : AbstractIntField(field, getter, setter) { - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeInt(this.field) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val value = stream.readInt() - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, true) - } else { - this.field = value - } - } - } - - /** - * Type specific field, storing primitive [Long] directly - */ - abstract inner class AbstractLongField(field: Long, private val getter: LongFieldGetter? = null, protected val setter: LongFieldSetter? = null) : PrimitiveField(), IMutableLongField { - private val subs = ILongSubcripable.Impl() - - override fun addListener(listener: LongConsumer): ISubscriptable.L { - return subs.addListener(listener) - } - - protected var field = field - set(value) { - if (field != value) { - field = value - subs.accept(value) - } - } - - final override val property = object : IMutableLongProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): Long { - return this@AbstractLongField.long - } - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { - this@AbstractLongField.long = value - } - } - - protected val access = object : LongFieldAccess { - override fun readLong(): Long { - return this@AbstractLongField.field - } - - override fun write(value: Long) { - if (!isDirty && value != this@AbstractLongField.field) { - notifyEndpoints(this@AbstractLongField) - isDirty = true - } - - this@AbstractLongField.field = value - } - } - - final override var long: Long - get() { - return getter?.invoke(access) ?: this.field - } - set(value) { - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, false) - } else if (value != this.field) { - if (!isDirty) { - notifyEndpoints(this) - isDirty = true - } - - this.field = value - } - } - } - - /** - * Type specific field, storing primitive [Long] directly, and networking it as variable length integer - */ - inner class LongField(field: Long, getter: LongFieldGetter? = null, setter: LongFieldSetter? = null) : AbstractLongField(field, getter, setter) { - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeVarLongLE(this.field) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val value = stream.readVarLongLE() - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, true) - } else { - this.field = value - } - } - } - - /** - * Type specific field, storing primitive [Long] directly, and networking it as 8 octets - */ - inner class FixedLongField(field: Long, getter: LongFieldGetter? = null, setter: LongFieldSetter? = null) : AbstractLongField(field, getter, setter) { - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeLong(this.field) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val value = stream.readLong() - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, true) - } else { - this.field = value - } - } - } - - /** - * Type specific field, storing primitive [Boolean] directly - */ - inner class BooleanField(field: Boolean, private val getter: BooleanFieldGetter? = null, private val setter: BooleanFieldSetter? = null) : PrimitiveField(), IMutableBooleanField { - private val subs = IBooleanSubscriptable.Impl() - - override fun addListener(listener: BooleanConsumer): ISubscriptable.L { - return subs.addListener(listener) - } - - private var field = field - set(value) { - if (field != value) { - field = value - subs.accept(value) - } - } - - override val property = object : IMutableBooleanProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { - return this@BooleanField.boolean - } - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { - this@BooleanField.boolean = value - } - } - - private val access = object : BooleanFieldAccess { - override fun readBoolean(): Boolean { - return this@BooleanField.field - } - - override fun write(value: Boolean) { - if (!isDirty && value != this@BooleanField.field) { - notifyEndpoints(this@BooleanField) - isDirty = true - } - - this@BooleanField.field = value - } - } - - override var boolean: Boolean - get() { - return getter?.invoke(access) ?: this.field - } - set(value) { - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, false) - } else if (value != this.field) { - if (!isDirty) { - notifyEndpoints(this) - isDirty = true - } - - this.field = value - } - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeBoolean(this.field) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val value = stream.readBoolean() - val setter = this.setter - - if (setter != null) { - setter.invoke(value, access, true) - } else { - this.field = value - } - } - } - - /** - * Networked value with backing getter which is constantly polled - */ - inner class ComputedField( - private val getter: () -> V, - private val codec: IStreamCodec, - observer: ((new: V) -> Unit)? = null - ) : AbstractField(), IField { - private var remote: Any? = Mark - private var clientValue: Any? = Mark - private val subs = ISubscriptable.Impl() - - init { - if (observer != null) { - subs.addListener(observer) - } - } - - override fun addListener(listener: Consumer): ISubscriptable.L { - return subs.addListener(listener) - } - - init { - observers.add(this) - } - - override fun observe(): Boolean { - check(!isRemoved) { "Field was removed" } - - val value = value - - if (!isDirty && (remote === Mark || !codec.compare(remote as V, value))) { - notifyEndpoints(this) - isDirty = true - remote = codec.copy(value) - } - - return isDirty - } - - override val value: V - get() { - val clientValue = clientValue - - if (clientValue === Mark) { - return getter.invoke() - } else { - return clientValue as V - } - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - codec.write(stream, value) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val newValue = codec.read(stream) - clientValue = newValue - subs.accept(newValue) - } - } - - /** - * Networked value with backing getter which is constantly polled - * - * This class has concrete implementation for [Float] primitive - */ - inner class ComputedFloatField(private val getter: FloatSupplier, observer: FloatConsumer? = null) : AbstractField(), IFloatField { - private var remote: Float = 0f - private var isRemoteSet = false - private var clientValue: Float = 0f - private var isClientValue = false - private val subs = IFloatSubcripable.Impl() - - init { - if (observer != null) { - subs.addListener(observer) - } - } - - override fun addListener(listener: FloatConsumer): ISubscriptable.L { - return subs.addListener(listener) - } - - override val property = object : IFloatProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): Float { - return float - } - } - - init { - observers.add(this) - } - - override fun observe(): Boolean { - check(!isRemoved) { "Field was removed" } - - val value = getter.getAsFloat() - - if (!isDirty && (!isRemoteSet || remote != value)) { - notifyEndpoints(this) - isDirty = true - isRemoteSet = true - remote = value - } - - return isDirty - } - - override fun markDirty() { - check(!isRemoved) { "Field was removed" } - notifyEndpoints(this) - isDirty = true - } - - override val float: Float - get() { - if (isClientValue) { - return clientValue - } else { - return getter.getAsFloat() - } - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeFloat(getter.getAsFloat()) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val newValue = stream.readFloat() - clientValue = newValue - isClientValue = true - subs.accept(newValue) - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Float { - return float - } - } - - /** - * Networked value with backing getter which is constantly polled - * - * This class has concrete implementation for [Double] primitive - */ - inner class ComputedDoubleField(private val getter: DoubleSupplier, observer: DoubleConsumer? = null) : AbstractField(), IDoubleField { - private var remote: Double = 0.0 - private var isRemoteSet = false - private var clientValue: Double = 0.0 - private var isClientValue = false - private val subs = IDoubleSubcripable.Impl() - - init { - if (observer != null) { - subs.addListener(observer) - } - } - - override fun addListener(listener: DoubleConsumer): ISubscriptable.L { - return subs.addListener(listener) - } - - override val property = object : IDoubleProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): Double { - return double - } - } - - init { - observers.add(this) - } - - override fun observe(): Boolean { - check(!isRemoved) { "Field was removed" } - - val value = getter.asDouble - - if (!isDirty && (!isRemoteSet || remote != value)) { - notifyEndpoints(this) - isDirty = true - isRemoteSet = true - remote = value - } - - return isDirty - } - - override val double: Double - get() { - if (isClientValue) { - return clientValue - } else { - return getter.asDouble - } - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeDouble(getter.asDouble) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val newValue = stream.readDouble() - clientValue = newValue - isClientValue = true - subs.accept(newValue) - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Double { - return double - } - } - - /** - * Networked value with backing getter which is constantly polled - * - * This class has concrete implementation for [Int] primitive - */ - abstract inner class AbstractComputedIntField(protected val getter: IntSupplier, observer: IntConsumer? = null) : AbstractField(), IIntField { - private var remote: Int = 0 - private var isRemoteSet = false - protected var clientValue: Int = 0 - set(value) { - isClientValue = true - - if (field != value) { - field = value - subs.accept(value) - } - } - - protected var isClientValue = false - private val subs = IIntSubcripable.Impl() - - init { - if (observer != null) { - subs.addListener(observer) - } - } - - override fun addListener(listener: IntConsumer): ISubscriptable.L { - return subs.addListener(listener) - } - - final override val property = object : IIntProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): Int { - return int - } - } - - init { - observers.add(this) - } - - final override fun observe(): Boolean { - check(!isRemoved) { "Field was removed" } - - val value = getter.asInt - - if (!isDirty && (!isRemoteSet || remote != value)) { - notifyEndpoints(this) - isDirty = true - isRemoteSet = true - remote = value - } - - return isDirty - } - - final override val int: Int - get() { - if (isClientValue) { - return clientValue - } else { - return getter.asInt - } - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Int { - return int - } - } - - /** - * Networked value with backing getter which is constantly polled - * - * This class has concrete implementation for [Int] primitive, networking it as variable length integer - */ - inner class ComputedIntField(getter: IntSupplier, observer: IntConsumer = IntConsumer {}) : AbstractComputedIntField(getter, observer) { - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeVarIntLE(getter.asInt) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - clientValue = stream.readVarIntLE() - } - } - - /** - * Networked value with backing getter which is constantly polled - * - * This class has concrete implementation for [Int] primitive, networking it as 4 octets - */ - inner class ComputedFixedIntField(getter: IntSupplier, observer: IntConsumer = IntConsumer {}) : AbstractComputedIntField(getter, observer) { - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeInt(getter.asInt) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - clientValue = stream.readInt() - } - } - - /** - * Networked value with backing getter which is constantly polled - * - * This class has concrete implementation for [Long] primitive - */ - abstract inner class AbstractComputedLongField(protected val getter: LongSupplier, observer: LongConsumer? = null) : AbstractField(), ILongField { - private var remote: Long = 0L - private var isRemoteSet = false - protected var clientValue: Long = 0L - set(value) { - isClientValue = true - - if (field != value) { - field = value - subs.accept(value) - } - } - - protected var isClientValue = false - private val subs = ILongSubcripable.Impl() - - init { - if (observer != null) { - subs.addListener(observer) - } - } - - override fun addListener(listener: LongConsumer): ISubscriptable.L { - return subs.addListener(listener) - } - - final override val property = object : ILongProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): Long { - return long - } - } - - init { - observers.add(this) - } - - final override fun observe(): Boolean { - check(!isRemoved) { "Field was removed" } - - val value = getter.asLong - - if (!isDirty && (!isRemoteSet || remote != value)) { - notifyEndpoints(this) - isDirty = true - isRemoteSet = true - remote = value - } - - return isDirty - } - - final override val long: Long - get() { - if (isClientValue) { - return clientValue - } else { - return getter.asLong - } - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Long { - return long - } - } - - /** - * Networked value with backing getter which is constantly polled - * - * This class has concrete implementation for [Long] primitive, networking it as variable length integer - */ - inner class ComputedLongField(getter: LongSupplier, observer: LongConsumer = LongConsumer {}) : AbstractComputedLongField(getter, observer) { - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeVarLongLE(getter.asLong) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - clientValue = stream.readVarLongLE() - } - } - - /** - * Networked value with backing getter which is constantly polled - * - * This class has concrete implementation for [Long] primitive, networking it as 8 octets - */ - inner class ComputedFixedLongField(getter: LongSupplier, observer: LongConsumer = LongConsumer {}) : AbstractComputedLongField(getter, observer) { - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeLong(getter.asLong) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - clientValue = stream.readLong() - } - } - - /** - * Networked value with backing getter which is constantly polled - * - * This class has concrete implementation for [Boolean] primitive - */ - inner class ComputedBooleanField(private val getter: BooleanSupplier, observer: BooleanConsumer? = null) : AbstractField(), IBooleanField { - private var remote: Boolean = false - private var isRemoteSet = false - private var clientValue: Boolean = false - private var isClientValue = false - private val subs = IBooleanSubscriptable.Impl() - - init { - if (observer != null) { - subs.addListener(observer) - } - } - - override fun addListener(listener: BooleanConsumer): ISubscriptable.L { - return subs.addListener(listener) - } - - override val property = object : IBooleanProperty { - override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { - return boolean - } - } - - init { - observers.add(this) - } - - override fun observe(): Boolean { - check(!isRemoved) { "Field was removed" } - - val value = getter.asBoolean - - if (!isDirty && (!isRemoteSet || remote != value)) { - notifyEndpoints(this) - isDirty = true - isRemoteSet = true - remote = value - } - - return isDirty - } - - override val boolean: Boolean - get() { - if (isClientValue) { - return clientValue - } else { - return getter.asBoolean - } - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - stream.writeBoolean(getter.asBoolean) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - val newValue = stream.readBoolean() - clientValue = newValue - isClientValue = true - subs.accept(newValue) - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { - return boolean - } - } - - /** - * Networked variable with backing field holding mutable value, which is constantly observed for changes - */ - inner class ObservedField : AbstractField, IMutableField { - private val codec: IStreamCodec - private val getter: () -> V - private val setter: (V) -> Unit - private var remote: V - private val subs = ISubscriptable.Impl() - - override fun addListener(listener: Consumer): ISubscriptable.L { - return subs.addListener(listener) - } - - override var value: V - get() = getter.invoke() - set(value) { setter.invoke(value) } - - constructor(field: KMutableProperty0, codec: IStreamCodec) : super() { - this.codec = codec - getter = field::get - setter = field::set - remote = codec.copy(value) - } - - constructor(getter: () -> V, setter: (V) -> Unit, codec: IStreamCodec) : super() { - this.codec = codec - this.getter = getter - this.setter = setter - remote = codec.copy(value) - } - - init { - observers.add(this) - } - - override fun observe(): Boolean { - check(!isRemoved) { "Field was removed" } - - val value = value - - if (!isDirty && !codec.compare(remote, value)) { - notifyEndpoints(this) - isDirty = true - remote = codec.copy(value) - } - - return isDirty - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - codec.write(stream, value) - isDirty = false - } - - override fun read(stream: DataInputStream) { - check(!isRemoved) { "Field was removed" } - this.value = codec.read(stream) - subs.accept(this.value) - } - } - - inner class Set( - private val codec: IStreamCodec, - private val backingSet: MutableSet, - private val callback: ((changes: Collection>) -> Unit)? = null, - ) : AbstractField>(), ISubscriptable> by ISubscriptable.empty() { - private var isRemote = false - - private fun pushBacklog(element: E, action: (DataOutputStream) -> Unit) { - check(!isRemote) { "Field marked as remote" } - - val pair = element to action - - forEachEndpoint { - val list = it.getSetBacklog(this) - val iterator = list.listIterator() - - for (value in iterator) { - if (value.first == element) { - iterator.remove() - } - } - - list.addLast(pair) - } - } - - override fun observe(): Boolean { - return false - } - - override fun remove() { - if (!isRemoved) { - forEachEndpoint { it.removeSetBacklog(this) } - } - - super.remove() - } - - override fun markDirty() { - check(!isRemoved) { "Field was removed" } - - if (isRemote || endpoints.isEmpty()) - return - - isDirty = true - - val endpoints = LinkedList Unit>>>() - - forEachEndpoint { - endpoints.add(it.getSetBacklog(this)) - it.addDirtyField(this) - } - - endpoints.forEach { - it.clear() - it.add(null to ClearBacklogEntry) - } - - for (value in backingSet) { - val valueCopy = codec.copy(value) - val pair: Pair Unit> = valueCopy to { it.write(ChangesetAction.ADD.ordinal + 1); codec.write(it, valueCopy) } - - endpoints.forEach { - it.add(pair) - } - } - } - - override fun markDirty(endpoint: Endpoint) { - super.markDirty(endpoint) - - endpoint.getSetBacklog(this).let { - it.clear() - it.add(null to ClearBacklogEntry) - - for (value in backingSet) { - val valueCopy = codec.copy(value) - it.add(valueCopy to { it.write(ChangesetAction.ADD.ordinal + 1); codec.write(it, valueCopy) }) - } - } - } - - override val value: MutableSet = object : MutableSet { - override fun add(element: E): Boolean { - if (backingSet.add(element)) { - if (!isRemote) { - markDirty() - - val copy = codec.copy(element) - - pushBacklog(element) { - it.write(ChangesetAction.ADD.ordinal + 1) - codec.write(it, copy) - } - } - - return true - } - - return false - } - - override fun addAll(elements: Collection): Boolean { - var any = false - elements.forEach { any = add(it) || any } - return any - } - - override fun clear() { - if (backingSet.isNotEmpty()) { - backingSet.clear() - - if (!isRemote) { - markDirty() - - forEachEndpoint { - it.getSetBacklog(this@Set).let { - it.clear() - it.add(null to ClearBacklogEntry) - } - } - } - } - } - - override fun iterator(): MutableIterator { - return object : MutableIterator { - private val parent = backingSet.iterator() - private var lastElement: Any? = Mark - - override fun hasNext(): Boolean { - return parent.hasNext() - } - - override fun next(): E { - return parent.next().also { lastElement = it } - } - - override fun remove() { - parent.remove() - val lastElement = lastElement - - if (lastElement !== Mark) { - this.lastElement = Mark - - if (!isRemote) { - markDirty() - - @Suppress("unchecked_cast") - pushBacklog(lastElement as E) { - it.write(ChangesetAction.REMOVE.ordinal + 1) - codec.write(it, lastElement as E) - } - } - } - } - } - } - - override fun remove(element: E): Boolean { - if (backingSet.remove(element)) { - if (!isRemote) { - markDirty() - - val copy = codec.copy(element) - - pushBacklog(element) { - it.write(ChangesetAction.REMOVE.ordinal + 1) - codec.write(it, copy) - } - } - - return true - } - - return false - } - - override fun removeAll(elements: Collection): Boolean { - var any = false - elements.forEach { any = remove(it) || any } - return any - } - - override fun retainAll(elements: Collection): Boolean { - var any = false - - val iterator = iterator() - - for (value in iterator) { - if (value !in elements) { - any = true - iterator.remove() - } - } - - return any - } - - override val size: Int - get() = backingSet.size - - override fun contains(element: E): Boolean { - return element in backingSet - } - - override fun containsAll(elements: Collection): Boolean { - return backingSet.containsAll(elements) - } - - override fun isEmpty(): Boolean { - return backingSet.isEmpty() - } - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - val list = endpoint.getSetBacklog(this) - - for (value in list) { - value.second.invoke(stream) - } - - stream.write(0) - list.clear() - isDirty = false - } - - override fun read(stream: DataInputStream) { - if (!isRemote) { - isRemote = true - forEachEndpoint { it.removeSetBacklog(this) } - } - - isDirty = false - - var action = stream.read() - val changeset = LinkedList>() - - while (action != 0) { - if ((action - 1) !in ChangesetActionList.indices) { - throw IllegalArgumentException("Unknown changeset action with index ${action - 1}") - } - - when (ChangesetActionList[action - 1]) { - ChangesetAction.CLEAR -> { - changeset.add(SetChangeset(ChangesetAction.CLEAR, null)) - backingSet.clear() - } - - ChangesetAction.ADD -> { - val read = codec.read(stream) - changeset.add(SetChangeset(ChangesetAction.ADD, read)) - backingSet.add(read) - } - - ChangesetAction.REMOVE -> { - val read = codec.read(stream) - changeset.add(SetChangeset(ChangesetAction.REMOVE, read)) - backingSet.remove(read) - } - } - - action = stream.read() - } - - callback?.invoke(changeset) - } - } - - inner class Map( - private val keyCodec: IStreamCodec, - private val valueCodec: IStreamCodec, - private val backingMap: MutableMap, - private val callback: ((changes: Collection>) -> Unit)? = null, - ) : AbstractField>(), IField>, ISubscriptable> by ISubscriptable.empty() { - private var sentAllValues = false - private var isRemote = false - - private fun pushBacklog(key: Any?, value: (DataOutputStream) -> Unit) { - val pair = key to value - - forEachEndpoint { - val list = it.getMapBacklog(this) - val iterator = list.listIterator() - - for (e in iterator) { - if (e.first == key) { - iterator.remove() - } - } - - list.addLast(pair) - } - } - - override fun observe(): Boolean { - return false - } - - override fun markDirty() { - check(!isRemoved) { "Field was removed" } - - if (isRemote || endpoints.isEmpty()) - return - - isDirty = true - val backlogs = LinkedList Unit>>>() - - forEachEndpoint { - it.addDirtyField(this) - val value = it.getMapBacklog(this) - backlogs.add(value) - value.clear() - value.add(null to ClearBacklogEntry) - } - - for ((key, value) in backingMap) { - val valueCopy = valueCodec.copy(value) - - val action = key to { it: DataOutputStream -> - it.write(ChangesetAction.ADD.ordinal + 1) - keyCodec.write(it, key) - valueCodec.write(it, valueCopy) - } - - for (backlog in backlogs) { - backlog.add(action) - } - } - } - - override fun markDirty(endpoint: Endpoint) { - check(!isRemoved) { "Field was removed" } - - if (isRemote) - return - - val backlog = endpoint.getMapBacklog(this) - - backlog.clear() - backlog.add(null to ClearBacklogEntry) - - for ((key, value) in backingMap) { - val valueCopy = valueCodec.copy(value) - - backlog.add(key to { - it.write(ChangesetAction.ADD.ordinal + 1) - keyCodec.write(it, key) - valueCodec.write(it, valueCopy) - }) - } - } - - private fun lmarkDirty() { - if (!isDirty) { - notifyEndpoints(this@Map) - isDirty = true - } - } - - override val value: MutableMap = object : ProxiedMap(backingMap) { - override fun onClear() { - if (isRemote || endpoints.isEmpty()) - return - - forEachEndpoint { endpoint -> - endpoint.getMapBacklog(this@Map).let { - it.clear() - it.add(null to ClearBacklogEntry) - } - } - - lmarkDirty() - this@FieldSynchronizer.isDirty = true - } - - override fun onValueAdded(key: K, value: V) { - if (isRemote || endpoints.isEmpty()) - return - - val keyCopy = keyCodec.copy(key) - val valueCopy = valueCodec.copy(value) - - pushBacklog(key) { - @Suppress("BlockingMethodInNonBlockingContext") // false positive - it.write(ChangesetAction.ADD.ordinal + 1) - keyCodec.write(it, keyCopy) - valueCodec.write(it, valueCopy) - } - - lmarkDirty() - } - - override fun onValueRemoved(key: K, value: V) { - if (isRemote || endpoints.isEmpty()) - return - - val keyCopy = keyCodec.copy(key) - - pushBacklog(key) { - @Suppress("BlockingMethodInNonBlockingContext") // false positive - it.write(ChangesetAction.REMOVE.ordinal + 1) - keyCodec.write(it, keyCopy) - } - - lmarkDirty() - } - } - - override fun write(stream: DataOutputStream, endpoint: Endpoint) { - sentAllValues = false - isDirty = false - - val iterator = endpoint.getMapBacklog(this).listIterator() - - for (entry in iterator) { - entry.second.invoke(stream) - iterator.remove() - } - - stream.write(0) - } - - override fun read(stream: DataInputStream) { - if (!isRemote) { - isRemote = true - forEachEndpoint { it.removeMapBacklog(this) } - } - - isDirty = false - - val changeset = LinkedList>() - var readAction = stream.read() - 1 - - while (readAction != -1) { - if (readAction >= ChangesetActionList.size) { - throw IndexOutOfBoundsException("Unknown map action with ID $readAction") - } - - when (ChangesetActionList[readAction]) { - ChangesetAction.CLEAR -> { - backingMap.clear() - changeset.add(ClearMapChangeset) - } - - ChangesetAction.ADD -> { - val key = keyCodec.read(stream) - val value = valueCodec.read(stream) - backingMap[key] = value - changeset.add(MapChangeset(ChangesetAction.ADD, key, value)) - } - - ChangesetAction.REMOVE -> { - val key = keyCodec.read(stream) - backingMap.remove(key) - changeset.add(MapChangeset(ChangesetAction.REMOVE, key, null)) - } - } - - readAction = stream.read() - 1 - } - - if (changeset.size != 0) { - callback?.invoke(changeset) - } - } - } - - /** - * marks all fields dirty, invalidates mappings for each endpoint - */ - fun invalidate() { - for (field in fields) { - field?.markDirty() - } - } - - /** - * Observe changes of all fields with backing computation lambda - */ - fun observe(): Boolean { - var changes = false - - if (observers.isNotEmpty()) { - for (field in observers) { - changes = field.observe() || changes - } - } - - return changes - } - - /** - * [defaultEndpoint]#collectNetworkPayload - */ - fun collectNetworkPayload(): FastByteArrayOutputStream? { - check(!defaultEndpoint.unused) { "Default endpoint is not used" } - observe() - val values = defaultEndpoint.collectNetworkPayload() - markClean() - return values - } - - fun read(stream: InputStream): Int { - var fieldId = stream.readVarIntLE() - var i = 0 - val dataStream = DataInputStream(stream) - - while (fieldId != 0) { - val field = fields.getOrNull(fieldId - 1) ?: throw IllegalArgumentException("Unknown field ID ${fieldId - 1}") - field.read(dataStream) - fieldId = stream.readVarIntLE() - i++ - } - - return i - } - - private object Mark - - companion object { - private val ClearBacklogEntry = { stream: DataOutputStream -> stream.write(ChangesetAction.CLEAR.ordinal + 1) } - private val ChangesetActionList = ChangesetAction.values() - private val ClearMapChangeset = MapChangeset(ChangesetAction.CLEAR, null, null) - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/Fields.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/Fields.kt deleted file mode 100644 index c3276c8cd..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/Fields.kt +++ /dev/null @@ -1,173 +0,0 @@ -package ru.dbotthepony.mc.otm.network.synchronizer - -import ru.dbotthepony.mc.otm.core.FloatSupplier -import ru.dbotthepony.mc.otm.core.IBooleanSubscriptable -import ru.dbotthepony.mc.otm.core.IDoubleSubcripable -import ru.dbotthepony.mc.otm.core.IFloatSubcripable -import ru.dbotthepony.mc.otm.core.IIntSubcripable -import ru.dbotthepony.mc.otm.core.ILongSubcripable -import ru.dbotthepony.mc.otm.core.ISubscriptable -import java.io.DataInputStream -import java.io.DataOutputStream -import java.util.function.BooleanSupplier -import java.util.function.DoubleSupplier -import java.util.function.IntSupplier -import java.util.function.LongSupplier -import java.util.function.Supplier -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty - -sealed interface IField : ReadOnlyProperty, Supplier, () -> V, ISubscriptable { - fun observe(): Boolean - fun markDirty() - fun markDirty(endpoint: FieldSynchronizer.Endpoint) - val value: V - val isRemoved: Boolean - - fun remove() - - fun write(stream: DataOutputStream, endpoint: FieldSynchronizer.Endpoint) - fun read(stream: DataInputStream) - - override fun getValue(thisRef: Any?, property: KProperty<*>): V { - return this.value - } - - override fun get(): V { - return value - } - - override fun invoke(): V { - return value - } -} - -interface IFloatProperty { - operator fun getValue(thisRef: Any?, property: KProperty<*>): Float -} - -sealed interface IFloatField : IField, FloatSupplier, IFloatSubcripable { - val float: Float - val property: IFloatProperty - - override val value: Float - get() = float - - @Deprecated("Use type specific Supplier interface") - override fun get(): Float { - return float - } - - override fun getAsFloat(): Float { - return float - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Float { - return float - } -} - -interface IDoubleProperty { - operator fun getValue(thisRef: Any?, property: KProperty<*>): Double -} - -sealed interface IDoubleField : IField, DoubleSupplier, IDoubleSubcripable { - val double: Double - val property: IDoubleProperty - - @Deprecated("Use type specific Supplier interface") - override fun get(): Double { - return double - } - - override val value: Double - get() = double - - override fun getAsDouble(): Double { - return double - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Double { - return double - } -} - -interface IIntProperty { - operator fun getValue(thisRef: Any?, property: KProperty<*>): Int -} - -sealed interface IIntField : IField, IntSupplier, IIntSubcripable { - val int: Int - val property: IIntProperty - - @Deprecated("Use type specific Supplier interface") - override fun get(): Int { - return int - } - - override val value: Int - get() = int - - override fun getAsInt(): Int { - return int - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Int { - return int - } -} - -interface ILongProperty { - operator fun getValue(thisRef: Any?, property: KProperty<*>): Long -} - -sealed interface ILongField : IField, LongSupplier, ILongSubcripable { - val long: Long - val property: ILongProperty - - @Deprecated("Use type specific Supplier interface") - override fun get(): Long { - return long - } - - override val value: Long - get() = long - - override fun getAsLong(): Long { - return long - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Long { - return long - } -} - -interface IBooleanProperty { - operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean -} - -sealed interface IBooleanField : IField, BooleanSupplier, IBooleanSubscriptable { - val boolean: Boolean - val property: IBooleanProperty - - @Deprecated("Use type specific Supplier interface") - override fun get(): Boolean { - return boolean - } - - override val value: Boolean - get() = boolean - - override fun getAsBoolean(): Boolean { - return boolean - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { - return boolean - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/MapChangeset.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/MapChangeset.kt deleted file mode 100644 index 47b1f5105..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/MapChangeset.kt +++ /dev/null @@ -1,23 +0,0 @@ -package ru.dbotthepony.mc.otm.network.synchronizer - -data class MapChangeset( - val action: ChangesetAction, - val key: K?, - val value: V? -) { - inline fun map(add: (K, V) -> Unit, remove: (K) -> Unit) { - when (action) { - ChangesetAction.ADD -> add.invoke(key!!, value!!) - ChangesetAction.REMOVE -> remove.invoke(key!!) - else -> {} - } - } - - inline fun map(add: (K, V) -> Unit, remove: (K) -> Unit, clear: () -> Unit) { - when (action) { - ChangesetAction.CLEAR -> clear.invoke() - ChangesetAction.ADD -> add.invoke(key!!, value!!) - ChangesetAction.REMOVE -> remove.invoke(key!!) - } - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/MutableFields.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/MutableFields.kt deleted file mode 100644 index 4f385ad01..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/MutableFields.kt +++ /dev/null @@ -1,166 +0,0 @@ -package ru.dbotthepony.mc.otm.network.synchronizer - -import it.unimi.dsi.fastutil.booleans.BooleanConsumer -import it.unimi.dsi.fastutil.floats.FloatConsumer -import ru.dbotthepony.mc.otm.core.GetterSetter -import ru.dbotthepony.mc.otm.core.SentientGetterSetter -import java.util.function.DoubleConsumer -import java.util.function.IntConsumer -import java.util.function.LongConsumer -import kotlin.reflect.KProperty - -sealed interface IMutableField : IField, SentientGetterSetter { - override fun getValue(thisRef: Any?, property: KProperty<*>): V { - return this.value - } - - override var value: V - - override fun accept(t: V) { - value = t - } - - override fun invoke(): V { - return this.value - } -} - -interface IMutableFloatProperty : IFloatProperty { - operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Float) -} - -sealed interface IMutableFloatField : IMutableField, IFloatField, FloatConsumer { - override var float: Float - override val property: IMutableFloatProperty - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.float")) - override var value: Float - get() = float - set(value) { float = value } - - override fun accept(t: Float) { - float = t - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Float { - return float - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Float) { - float = value - } -} - -interface IMutableDoubleProperty : IDoubleProperty { - operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) -} - -sealed interface IMutableDoubleField : IMutableField, IDoubleField, DoubleConsumer { - override var double: Double - override val property: IMutableDoubleProperty - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.double")) - override var value: Double - get() = double - set(value) { double = value } - - override fun accept(t: Double) { - double = t - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Double { - return double - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) { - double = value - } -} - -interface IMutableIntProperty : IIntProperty { - operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) -} - -sealed interface IMutableIntField : IMutableField, IIntField, IntConsumer { - override var int: Int - override val property: IMutableIntProperty - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.int")) - override var value: Int - get() = int - set(value) { int = value } - - override fun accept(t: Int) { - int = t - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Int { - return int - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { - int = value - } -} - -interface IMutableLongProperty : ILongProperty { - operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) -} - -sealed interface IMutableLongField : IMutableField, ILongField, LongConsumer { - override var long: Long - override val property: IMutableLongProperty - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.long")) - override var value: Long - get() = long - set(value) { long = value } - - override fun accept(t: Long) { - long = t - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Long { - return long - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { - long = value - } -} - -interface IMutableBooleanProperty : IBooleanProperty { - operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) -} - -sealed interface IMutableBooleanField : IMutableField, IBooleanField, BooleanConsumer { - override var boolean: Boolean - override val property: IMutableBooleanProperty - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.boolean")) - override var value: Boolean - get() = boolean - set(value) { boolean = value } - - override fun accept(t: Boolean) { - boolean = t - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { - return boolean - } - - @Deprecated("Use type specific property", replaceWith = ReplaceWith("this.property")) - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { - boolean = value - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/SetChangeset.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/SetChangeset.kt deleted file mode 100644 index 8c8894616..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/SetChangeset.kt +++ /dev/null @@ -1,22 +0,0 @@ -package ru.dbotthepony.mc.otm.network.synchronizer - -data class SetChangeset( - val action: ChangesetAction, - val value: V? -) { - inline fun map(add: (V) -> Unit, remove: (V) -> Unit) { - when (action) { - ChangesetAction.ADD -> add.invoke(value!!) - ChangesetAction.REMOVE -> remove.invoke(value!!) - else -> {} - } - } - - inline fun map(add: (V) -> Unit, remove: (V) -> Unit, clear: () -> Unit) { - when (action) { - ChangesetAction.CLEAR -> clear.invoke() - ChangesetAction.ADD -> add.invoke(value!!) - ChangesetAction.REMOVE -> remove.invoke(value!!) - } - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockColors.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockColors.kt index 7d17ee06e..5157edd89 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockColors.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockColors.kt @@ -10,7 +10,7 @@ import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.client.event.RegisterColorHandlersEvent import net.minecraftforge.eventbus.api.IEventBus import ru.dbotthepony.mc.otm.block.entity.decorative.HoloSignBlockEntity -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor object MBlockColors { private const val DEFAULT_WATER_TINT: Int = 0x3F76E4 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt index 417aae832..26d713d72 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt @@ -50,7 +50,7 @@ import ru.dbotthepony.mc.otm.client.MatteryGUI import ru.dbotthepony.mc.otm.compat.vanilla.MatteryChestMenu import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom import ru.dbotthepony.mc.otm.core.math.Decimal -import ru.dbotthepony.mc.otm.core.math.RGBAColor +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.data.DecimalProvider import ru.dbotthepony.mc.otm.isClient import ru.dbotthepony.mc.otm.item.weapon.EnergySwordItem diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStorageStack.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStorageStack.kt index 260ca07bc..c58cbf17f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStorageStack.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStorageStack.kt @@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.storage import net.minecraft.network.chat.Component import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.core.getValue import ru.dbotthepony.mc.otm.core.lazy2 import ru.dbotthepony.mc.otm.core.math.toIntSafe diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/StorageStack.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/StorageStack.kt index 75081b50e..6b161f570 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/StorageStack.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/StorageStack.kt @@ -5,6 +5,7 @@ import net.minecraft.network.FriendlyByteBuf import net.minecraft.world.item.ItemStack import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.registries.DeferredRegister +import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.core.getValue import ru.dbotthepony.mc.otm.core.math.Decimal diff --git a/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FieldSynchronizerTests.kt b/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FieldSynchronizerTests.kt deleted file mode 100644 index 001768a4e..000000000 --- a/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FieldSynchronizerTests.kt +++ /dev/null @@ -1,134 +0,0 @@ -package ru.dbotthepony.mc.otm.tests - -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test -import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer -import ru.dbotthepony.mc.otm.network.synchronizer.IMutableField -import java.io.ByteArrayInputStream - -object FieldSynchronizerTests { - @Test - @DisplayName("Field Synchronizer full read/write test") - fun test() { - val a = FieldSynchronizer() - val b = FieldSynchronizer() - - val boolA = a.bool() - val boolB = b.bool() - - val intA = a.int() - val intB = b.int() - - val intA2 = a.int() - val intB2 = b.int() - - val intA3 = a.int() - val intB3 = b.int() - - boolA.value = true - intA.value = 8384 - intA2.value = 348488 - intA3.value = -4 - - b.read(a.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) }) - - assertEquals(boolA.value, boolB.value) - assertEquals(intA.value, intB.value) - assertEquals(intA2.value, intB2.value) - assertEquals(intA3.value, intB3.value) - } - - @Test - @DisplayName("Field Synchronizer partial read/write test") - fun testPartial() { - val a = FieldSynchronizer() - val b = FieldSynchronizer() - - val boolA = a.bool() - val boolB = b.bool() - - val intA = a.int() - val intB = b.int() - - val intA2 = a.int() - val intB2 = b.int() - - val intA3 = a.int() - val intB3 = b.int() - - boolA.value = true - //intA.setValue(8384) - //intA2.setValue(348488) - intA3.value = -4 - - b.read(a.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) }) - - assertEquals(boolA.value, boolB.value) - assertEquals(intA.value, intB.value) - assertEquals(intA2.value, intB2.value) - assertEquals(intA3.value, intB3.value) - } - - @Test - @DisplayName("Field Synchronizer multiple endpoints") - fun multipleEndpoints() { - val a = FieldSynchronizer() - val b = FieldSynchronizer() - val c = FieldSynchronizer() - - val f1 = a.bool() - val f2 = a.bool() - val f3 = a.int() - val f4 = a.long() - - val aFields = listOf(f1, f2, f3, f4) - val bFields = listOf(b.bool(), b.bool(), b.int(), b.long()) - val cFields = listOf(c.bool(), c.bool(), c.int(), c.long()) - - val bEndpoint = a.Endpoint() - - f2.value = true - f3.value = -15 - - val cEndpoint = a.Endpoint() - - f4.value = 80L - - b.read(bEndpoint.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) }) - c.read(cEndpoint.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) }) - - for ((i, field) in bFields.withIndex()) { - assertEquals(aFields[i].value, field.value) - } - - for ((i, field) in cFields.withIndex()) { - assertEquals(aFields[i].value, field.value) - } - } - - @Test - @DisplayName("Field Synchronizer Lotta fields") - fun lottaFields() { - val a = FieldSynchronizer() - val b = FieldSynchronizer() - - val fieldsa = ArrayList>() - val fieldsb = ArrayList>() - - for (i in 0 .. 900) { - fieldsa.add(a.int()) - fieldsb.add(b.int()) - } - - for (i in 0 .. 900) { - fieldsa[i].value = i - } - - b.read(a.collectNetworkPayload()!!.let { ByteArrayInputStream(it.array, 0, it.length) }) - - for (i in 0 .. 900) { - assertEquals(fieldsa[i].value, fieldsb[i].value) - } - } -}