From a51a4a3ad081f56f4ed13e3508d567ab2322b906 Mon Sep 17 00:00:00 2001 From: YuRaNnNzZZ Date: Mon, 22 Jan 2024 20:25:47 +0300 Subject: [PATCH 01/38] datagen biome modifiers for ores --- .../ru/dbotthepony/mc/otm/datagen/DataGen.kt | 2 + .../ru/dbotthepony/mc/otm/datagen/OreGen.kt | 58 ++++++++++++++++--- .../overdrive_that_matters/tritanium_ore.json | 9 --- 3 files changed, 53 insertions(+), 16 deletions(-) delete mode 100644 src/main/resources/data/overdrive_that_matters/forge/biome_modifier/overdrive_that_matters/tritanium_ore.json diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt index 71851784c..92894f6aa 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt @@ -20,6 +20,7 @@ import net.minecraftforge.common.data.ForgeAdvancementProvider import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.fml.common.Mod import net.minecraftforge.data.event.GatherDataEvent +import net.minecraftforge.registries.ForgeRegistries import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.android.AndroidResearchDataProvider import ru.dbotthepony.mc.otm.block.* @@ -531,6 +532,7 @@ object DataGen { .add(Registries.DAMAGE_TYPE, ::registerDamageTypes) .add(Registries.CONFIGURED_FEATURE, ::registerConfiguredFeatures) .add(Registries.PLACED_FEATURE, ::registerPlacedFeatures) + .add(ForgeRegistries.Keys.BIOME_MODIFIERS, ::registerBiomeModifiers) event.generator.addProvider(event.includeServer(), DatapackBuiltinEntriesProvider(event.generator.packOutput, event.lookupProvider, registrySetBuilder, setOf(MOD_ID))) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/OreGen.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/OreGen.kt index 2e7de16ef..f438c84d7 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/OreGen.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/OreGen.kt @@ -1,10 +1,13 @@ package ru.dbotthepony.mc.otm.datagen +import net.minecraft.core.HolderSet import net.minecraft.core.RegistrySetBuilder import net.minecraft.core.registries.Registries import net.minecraft.data.worldgen.BootstapContext import net.minecraft.resources.ResourceKey +import net.minecraft.tags.BiomeTags import net.minecraft.tags.BlockTags +import net.minecraft.world.level.levelgen.GenerationStep import net.minecraft.world.level.levelgen.VerticalAnchor import net.minecraft.world.level.levelgen.feature.ConfiguredFeature import net.minecraft.world.level.levelgen.feature.Feature @@ -15,10 +18,19 @@ import net.minecraft.world.level.levelgen.placement.InSquarePlacement import net.minecraft.world.level.levelgen.placement.PlacedFeature import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider +import net.minecraftforge.common.world.BiomeModifier +import net.minecraftforge.common.world.ForgeBiomeModifiers import net.minecraftforge.data.event.GatherDataEvent +import net.minecraftforge.registries.ForgeRegistries import ru.dbotthepony.mc.otm.registry.MBlocks -private val oreKey by lazy { ResourceKey.create(Registries.CONFIGURED_FEATURE, modLocation("tritanium_ore")) } +private object ConfiguredFeatures { + val TRITANIUM_ORE = key("tritanium_ore") + + private fun key(name: String): ResourceKey> { + return ResourceKey.create(Registries.CONFIGURED_FEATURE, modLocation(name)) + } +} fun registerConfiguredFeatures(context: BootstapContext>) { val stone = TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES) @@ -29,16 +41,23 @@ fun registerConfiguredFeatures(context: BootstapContext> OreConfiguration.target(deepslate, MBlocks.DEEPSLATE_TRITANIUM_ORE.defaultBlockState()), ) - context.register(oreKey, ConfiguredFeature(Feature.ORE, OreConfiguration(target, 9))) + context.register(ConfiguredFeatures.TRITANIUM_ORE, ConfiguredFeature(Feature.ORE, OreConfiguration(target, 9))) +} + +private object PlacedFeatures { + val NORMAL_TRITANIUM = key("normal_tritanium") + val DEEP_TRITANIUM = key("deep_tritanium") + + private fun key(name: String): ResourceKey { + return ResourceKey.create(Registries.PLACED_FEATURE, modLocation(name)) + } } fun registerPlacedFeatures(context: BootstapContext) { - fun location(name: String) = ResourceKey.create(Registries.PLACED_FEATURE, modLocation(name)) - val configured = context.lookup(Registries.CONFIGURED_FEATURE) - val ore = configured.getOrThrow(oreKey) + val ore = configured.getOrThrow(ConfiguredFeatures.TRITANIUM_ORE) - context.register(location("normal_tritanium"), PlacedFeature( + context.register(PlacedFeatures.NORMAL_TRITANIUM, PlacedFeature( ore, listOf( CountPlacement.of(8), @@ -47,7 +66,7 @@ fun registerPlacedFeatures(context: BootstapContext) { ) )) - context.register(location("deep_tritanium"), PlacedFeature( + context.register(PlacedFeatures.DEEP_TRITANIUM, PlacedFeature( ore, listOf( CountPlacement.of(10), @@ -56,3 +75,28 @@ fun registerPlacedFeatures(context: BootstapContext) { ) )) } + +private object BiomeModifiers { + val TRITANIUM_ORE = key("tritanium_ore") + + private fun key(name: String): ResourceKey { + return ResourceKey.create(ForgeRegistries.Keys.BIOME_MODIFIERS, modLocation(name)) + } +} + +fun registerBiomeModifiers(context: BootstapContext) { + val placed = context.lookup(Registries.PLACED_FEATURE) + val biomes = context.lookup(Registries.BIOME) + + context.register( + BiomeModifiers.TRITANIUM_ORE, + ForgeBiomeModifiers.AddFeaturesBiomeModifier( + biomes.getOrThrow(BiomeTags.IS_OVERWORLD), + HolderSet.direct( + placed.getOrThrow(PlacedFeatures.NORMAL_TRITANIUM), + placed.getOrThrow(PlacedFeatures.DEEP_TRITANIUM) + ), + GenerationStep.Decoration.UNDERGROUND_ORES + ) + ) +} diff --git a/src/main/resources/data/overdrive_that_matters/forge/biome_modifier/overdrive_that_matters/tritanium_ore.json b/src/main/resources/data/overdrive_that_matters/forge/biome_modifier/overdrive_that_matters/tritanium_ore.json deleted file mode 100644 index 2624ac791..000000000 --- a/src/main/resources/data/overdrive_that_matters/forge/biome_modifier/overdrive_that_matters/tritanium_ore.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "type": "forge:add_features", - "biomes": "#minecraft:is_overworld", - "features": [ - "overdrive_that_matters:deep_tritanium", - "overdrive_that_matters:normal_tritanium" - ], - "step": "underground_ores" -} From 306cad582efeb3611a4a0cd50beff00148338dc2 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 26 Jan 2024 15:18:28 +0700 Subject: [PATCH 02/38] Fix tritanium pressure plates having collision --- .../mc/otm/block/decorative/TritaniumPressurePlate.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt index 3719acfb7..68cf09679 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt @@ -21,7 +21,7 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.collect.iteratorOf import ru.dbotthepony.mc.otm.core.get -class TritaniumPressurePlate(color: DyeColor?) : BasePressurePlateBlock(Properties.of().mapColor(color ?: DyeColor.LIGHT_BLUE).sound(SoundType.METAL).explosionResistance(80f).noOcclusion().destroyTime(3f).requiresCorrectToolForDrops(), BlockSetType.IRON) { +class TritaniumPressurePlate(color: DyeColor?) : BasePressurePlateBlock(Properties.of().mapColor(color ?: DyeColor.LIGHT_BLUE).sound(SoundType.METAL).explosionResistance(80f).noOcclusion().destroyTime(3f).requiresCorrectToolForDrops().forceSolidOn().noCollission(), BlockSetType.IRON) { val tooltips = TooltipList() override fun appendHoverText( From f29e4b29d740657105edb28c89cdd173a5f71442 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 26 Jan 2024 18:30:53 +0700 Subject: [PATCH 03/38] Make painter table accept water directly from fluid containers --- .../mc/otm/block/decorative/PainterBlock.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/PainterBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/PainterBlock.kt index c13cce68a..d471cda7e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/PainterBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/PainterBlock.kt @@ -1,12 +1,17 @@ package ru.dbotthepony.mc.otm.block.decorative import net.minecraft.core.BlockPos +import net.minecraft.world.InteractionHand +import net.minecraft.world.InteractionResult +import net.minecraft.world.entity.player.Player import net.minecraft.world.level.Level import net.minecraft.world.level.block.EntityBlock import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.entity.BlockEntityTicker import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.phys.BlockHitResult +import net.minecraftforge.fluids.FluidUtil import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity @@ -15,6 +20,15 @@ class PainterBlock : RotatableMatteryBlock(DEFAULT_MACHINE_PROPERTIES), EntityBl return PainterBlockEntity(p_153215_, p_153216_) } + @Suppress("OVERRIDE_DEPRECATION") + override fun use(blockState: BlockState, level: Level, blockPos: BlockPos, ply: Player, hand: InteractionHand, blockHitResult: BlockHitResult): InteractionResult { + if (FluidUtil.interactWithFluidHandler(ply, hand, level, blockPos, blockHitResult.direction)) { + return InteractionResult.sidedSuccess(level.isClientSide) + } + + return super.use(blockState, level, blockPos, ply, hand, blockHitResult) + } + override fun getTicker(p_153212_: Level, p_153213_: BlockState, p_153214_: BlockEntityType): BlockEntityTicker? { if (p_153212_.isClientSide) return null return BlockEntityTicker { p_155253_, p_155254_, p_155255_, p_155256_ -> if (p_155256_ is PainterBlockEntity) p_155256_.tick() } From 3a4d80d0847796623ca520079904c459cc778aed Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 26 Jan 2024 19:16:36 +0700 Subject: [PATCH 04/38] Mark liquid xp as forge:experience --- src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt index 2872dfa19..8aa8bcef3 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt @@ -11,6 +11,7 @@ import net.minecraft.world.level.block.Blocks import net.minecraftforge.common.Tags import ru.dbotthepony.mc.otm.registry.MBlockTags import ru.dbotthepony.mc.otm.registry.MBlocks +import ru.dbotthepony.mc.otm.registry.MFluids import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MRegistry @@ -29,6 +30,9 @@ fun addTags(tagsProvider: TagsProvider) { tagsProvider.plates.add("gold", MItems.GOLD_PLATE) tagsProvider.plates.add("carbon", MItems.CARBON_MESH) + tagsProvider.fluids.forge("experience").add(MFluids.LIQUID_XP).add(MFluids.LIQUID_XP_FLOWING) + tagsProvider.fluidTypes.forge("experience").add(MFluids.LIQUID_XP_TYPE) + tagsProvider.items.forge("reinforced_tritanium").add(MItems.REINFORCED_TRITANIUM_PLATE) tagsProvider.storageBlocksAsItem.add("tritanium", MItems.TRITANIUM_INGOT_BLOCK) From 7e5711d210e17ed9f7e9fd2b910127c63243b052 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sat, 27 Jan 2024 10:23:29 +0700 Subject: [PATCH 05/38] Fix android getting duplicated energy on death if they have battery equipped --- .../dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt index 8e6479d46..4be4518dc 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -1592,7 +1592,9 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial mattery.iteration++ mattery.shouldSendIteration = true mattery.deathLog.addLast(ply.tickCount to ply.combatTracker.deathMessage) - mattery.androidEnergy.batteryLevel = mattery.androidEnergy.batteryLevel.coerceAtLeast(AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2")) // если смерть была от разряда батареи, то предотвращаем софтлок + + if (mattery.androidEnergy.batteryLevel < AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2")) + mattery.androidEnergy.batteryLevel = AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2") // если смерть была от разряда батареи, то предотвращаем софтлок while (mattery.deathLog.size > 6) { mattery.deathLog.removeFirst() From cd5f9dff2e9da7e04a6bdc7145402c524acf7937 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sun, 28 Jan 2024 23:23:21 +0700 Subject: [PATCH 06/38] Un-seal BlockEnergyStorageImpl --- .../capability/energy/BlockEnergyStorageImpl.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BlockEnergyStorageImpl.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BlockEnergyStorageImpl.kt index 997474504..a798bb3f6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BlockEnergyStorageImpl.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BlockEnergyStorageImpl.kt @@ -13,13 +13,25 @@ import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.nbt.mapPresent import ru.dbotthepony.mc.otm.core.nbt.set -sealed class BlockEnergyStorageImpl( +open class BlockEnergyStorageImpl( protected val listener: () -> Unit, final override val energyFlow: FlowDirection, private val maxBatteryLevelProvider: () -> Decimal, private val maxInputProvider: () -> Decimal?, private val maxOutputProvider: () -> Decimal?, ) : IMatteryEnergyStorage, INBTSerializable, IEnergyStorageImpl { + constructor( + listener: () -> Unit, + energyFlow: FlowDirection, + values: EnergyBalanceValues + ) : this(listener, energyFlow, values::energyCapacity, values::energyThroughput, values::energyThroughput) + + constructor( + listener: () -> Unit, + energyFlow: FlowDirection, + values: VerboseEnergyBalanceValues + ) : this(listener, energyFlow, values::energyCapacity, values::maxEnergyReceive, values::maxEnergyExtract) + private var maxInputStorage: Decimal? = null private var maxOutputStorage: Decimal? = null private var maxBatteryLevelStorage: Decimal? = null From dafa54112efa71bcf0166021b63aca35b69dfb35 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sun, 28 Jan 2024 23:23:48 +0700 Subject: [PATCH 07/38] Forgot to commit tagsprovider for fluid tags --- .../kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt index b40a2b563..41ad89edd 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt @@ -167,6 +167,8 @@ class TagsProvider(private val event: GatherDataEvent) { val blocks = Delegate(ForgeRegistries.BLOCKS) val items = Delegate(ForgeRegistries.ITEMS) + val fluids = Delegate(ForgeRegistries.FLUIDS) + val fluidTypes = Delegate(ForgeRegistries.Keys.FLUID_TYPES) val mobEffects = Delegate(ForgeRegistries.MOB_EFFECTS) val damageTypes = Delegate(Registries.DAMAGE_TYPE) From 2a8cabe577e8b054b029924ef428b0ae56d2e511 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sun, 28 Jan 2024 23:24:24 +0700 Subject: [PATCH 08/38] Force directional multiblock and multiblock performance improvements --- .../ru/dbotthepony/mc/otm/core/Multiblock.kt | 79 +++++++++++++++---- 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt index 6637b2fdf..f908f54f5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt @@ -9,14 +9,17 @@ import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap import net.minecraft.core.BlockPos import net.minecraft.core.Direction +import net.minecraft.core.SectionPos import net.minecraft.core.Vec3i import net.minecraft.tags.TagKey import net.minecraft.world.level.Level import net.minecraft.world.level.LevelAccessor import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.Blocks import net.minecraft.world.level.block.Rotation import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.chunk.ChunkStatus import ru.dbotthepony.mc.otm.core.collect.WeakHashSet import ru.dbotthepony.mc.otm.core.collect.collect import ru.dbotthepony.mc.otm.core.collect.map @@ -119,9 +122,9 @@ class MultiblockBuilder { } @Suppress("unchecked_cast") - abstract class BlockPredicates> { + abstract class Part> { val predicates = ObjectArraySet() - val children = ObjectArraySet>() + val children = ObjectArraySet>() val blockStateTags = ObjectArraySet() val blockTags = ObjectArraySet() @@ -153,12 +156,20 @@ class MultiblockBuilder { } fun block(block: Block): T { - predicates.add { pos, access -> access.getBlockState(pos).`is`(block) } + predicates.add { pos, access -> + // use getChunk directly because we don't want to chunkload + (access.getChunk(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z), ChunkStatus.FULL, false)?.getBlockState(pos) ?: Blocks.AIR.defaultBlockState()).`is`(block) + } + return this as T } fun block(block: TagKey): T { - predicates.add { pos, access -> access.getBlockState(pos).`is`(block) } + predicates.add { pos, access -> + // use getChunk directly because we don't want to chunkload + (access.getChunk(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z), ChunkStatus.FULL, false)?.getBlockState(pos) ?: Blocks.AIR.defaultBlockState()).`is`(block) + } + return this as T } @@ -168,7 +179,11 @@ class MultiblockBuilder { } fun block(state: BlockState): T { - predicates.add { pos, access -> access.getBlockState(pos) == state } + predicates.add { pos, access -> + // use getChunk directly because we don't want to chunkload + access.getChunk(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z), ChunkStatus.FULL, false)?.getBlockState(pos) == state + } + return this as T } @@ -201,7 +216,7 @@ class MultiblockBuilder { abstract val strategy: Strategy } - class And

>(val parent: P) : BlockPredicates>() { + class And

>(val parent: P) : Part>() { init { parent.children.add(this) } @@ -212,7 +227,7 @@ class MultiblockBuilder { get() = Strategy.AND } - class Or

>(val parent: P) : BlockPredicates>() { + class Or

>(val parent: P) : Part>() { init { parent.children.add(this) } @@ -226,7 +241,7 @@ class MultiblockBuilder { /** * Behaves as if being [Or] node */ - inner class Node(val pos: BlockPos) : BlockPredicates() { + inner class Node(val pos: BlockPos) : Part() { init { check(nodes.put(pos, this) == null) { "Trying to create new node at $pos while already having one" } } @@ -433,8 +448,8 @@ class Multiblock( } } - private inner class Config(val pos: BlockPos, parts: Collection) { - private inner class Part(val pos: BlockPos, val prototype: MultiblockFactory.Part) { + private inner class Config(val direction: Direction, val pos: BlockPos, parts: Collection) { + private inner class Part(val pos: BlockPos, val prototype: MultiblockFactory.Part) : Comparable { private var blockEntity: BlockEntity? = null private var blockState: BlockState? = null private val assignedBlockEntityLists = ArrayList>(prototype.blockEntityTags.size) @@ -442,6 +457,12 @@ class Multiblock( private val assignedBlockLists = ArrayList>() private val children: ImmutableList = prototype.children.stream().map { Part(pos, it) }.collect(ImmutableList.toImmutableList()) + override fun compareTo(other: Part): Int { + val cmp = SectionPos.blockToSectionCoord(pos.x).compareTo(SectionPos.blockToSectionCoord(other.pos.x)) + if (cmp != 0) return cmp + return SectionPos.blockToSectionCoord(pos.z).compareTo(SectionPos.blockToSectionCoord(other.pos.z)) + } + init { prototype.blockEntityTags.forEach { assignedBlockEntityLists.add(tag2BlockEntity.computeIfAbsent(it, Object2ObjectFunction { _ -> BEList(it as MultiblockBuilder.EntityTag).also { blockEntityLists.add(it) } })) @@ -596,7 +617,10 @@ class Multiblock( private val blockStateLists = ArrayList>() private val blockLists = ArrayList>() - private val parts: ImmutableSet = parts.stream().map { Part(it.pos + pos, it) }.collect(ImmutableSet.toImmutableSet()) + private val parts: ImmutableList = parts.stream() + .map { Part(it.pos + pos, it) } + .sorted() // group/localize parts by in-world chunks to maximize getChunk() cache hit rate + .collect(ImmutableList.toImmutableList()) fun clear() { blockEntityLists.forEach { it.clear() } @@ -634,13 +658,16 @@ class Multiblock( } } - private val north = Config(pos, north).also { configurations.add(it) } - private val south = Config(pos, south).also { configurations.add(it) } - private val west = Config(pos, west).also { configurations.add(it) } - private val east = Config(pos, east).also { configurations.add(it) } + private val north = Config(Direction.NORTH, pos, north).also { configurations.add(it) } + private val south = Config(Direction.SOUTH, pos, south).also { configurations.add(it) } + private val west = Config(Direction.WEST, pos, west).also { configurations.add(it) } + private val east = Config(Direction.EAST, pos, east).also { configurations.add(it) } private var activeConfig: Config? = null + val currentDirection: Direction? + get() = activeConfig?.direction + fun blockEntities(tag: MultiblockBuilder.EntityTag): Set { if (!isValid) return emptySet() return activeConfig?.blockEntities(tag) ?: setOf() @@ -678,4 +705,26 @@ class Multiblock( return false } } + + fun update(levelAccessor: LevelAccessor, direction: Direction): Boolean { + if (activeConfig?.direction != direction) { + activeConfig?.clear() + activeConfig = null + } + + val config = when (direction) { + Direction.NORTH -> north + Direction.SOUTH -> south + Direction.WEST -> west + Direction.EAST -> east + else -> throw IllegalArgumentException(direction.name) + } + + isValid = config.update(levelAccessor) + + if (isValid) + activeConfig = config + + return isValid + } } From eb60c371ed117c763258f66b855dba9ed76e6524 Mon Sep 17 00:00:00 2001 From: GearShocky Date: Mon, 29 Jan 2024 02:54:49 +0600 Subject: [PATCH 09/38] Painting table and water source models --- .../models/block/painting_table.json | 233 ++++++++++++++++++ .../models/block/water_source.json | 164 ++++++++++++ .../textures/block/painting_table.png | Bin 0 -> 831 bytes .../textures/block/water_source.png | Bin 0 -> 542 bytes .../textures/block/water_source_mask.png | Bin 0 -> 284 bytes .../textures/block/water_source_misc.png | Bin 0 -> 401 bytes .../textures/block/water_source_pump.png | Bin 0 -> 554 bytes .../block/water_source_pump.png.mcmeta | 6 + 8 files changed, 403 insertions(+) create mode 100644 src/main/resources/assets/overdrive_that_matters/models/block/painting_table.json create mode 100644 src/main/resources/assets/overdrive_that_matters/models/block/water_source.json create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/block/painting_table.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/block/water_source.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/block/water_source_mask.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/block/water_source_misc.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png.mcmeta diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/painting_table.json b/src/main/resources/assets/overdrive_that_matters/models/block/painting_table.json new file mode 100644 index 000000000..eda781060 --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/models/block/painting_table.json @@ -0,0 +1,233 @@ +{ + "credit": "Made with Blockbench", + "render_type": "cutout", + "texture_size": [64, 32], + "textures": { + "0": "overdrive_that_matters:block/painting_table", + "particle": "overdrive_that_matters:block/painting_table" + }, + "elements": [ + { + "name": "body", + "from": [0, 8, 0], + "to": [16, 10, 16], + "faces": { + "north": {"uv": [0, 11, 4, 12], "texture": "#0"}, + "east": {"uv": [8, 3, 4, 4], "texture": "#0"}, + "south": {"uv": [12, 11, 16, 12], "texture": "#0"}, + "west": {"uv": [4, 3, 8, 4], "texture": "#0"}, + "up": {"uv": [0, 0, 4, 8], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 8], "texture": "#0"} + } + }, + { + "name": "body", + "from": [0, 0, 0], + "to": [16, 2, 15], + "faces": { + "north": {"uv": [0, 15, 4, 16], "texture": "#0"}, + "east": {"uv": [7.75, 7, 4, 8], "texture": "#0"}, + "south": {"uv": [12, 15, 16, 16], "texture": "#0"}, + "west": {"uv": [4, 7, 7.75, 8], "texture": "#0"}, + "up": {"uv": [0, 0, 4, 7.5], "texture": "#0"}, + "down": {"uv": [0, 0, 4, 7.5], "texture": "#0"} + } + }, + { + "name": "body", + "from": [0, 2, 5], + "to": [16, 8, 15], + "faces": { + "north": {"uv": [0, 12, 4, 15], "texture": "#0"}, + "east": {"uv": [7.75, 4, 5.25, 7], "texture": "#0"}, + "south": {"uv": [12, 12, 16, 15], "texture": "#0"}, + "west": {"uv": [5.25, 4, 7.75, 7], "texture": "#0"} + } + }, + { + "name": "body", + "from": [0, 10, 9], + "to": [16, 16, 16], + "faces": { + "north": {"uv": [4, 11.5, 8, 14.5], "texture": "#0"}, + "east": {"uv": [7.75, 0, 6, 3], "texture": "#0"}, + "south": {"uv": [12, 8, 16, 11], "texture": "#0"}, + "west": {"uv": [6, 0, 7.75, 3], "texture": "#0"}, + "up": {"uv": [4, 8, 8, 11.5], "rotation": 180, "texture": "#0"} + } + }, + { + "name": "cartridge", + "from": [10, 2, 1], + "to": [12, 8, 5], + "faces": { + "north": {"uv": [8.75, 0, 9.25, 3], "texture": "#0"}, + "east": {"uv": [7.75, 0, 8.75, 3], "texture": "#0"}, + "west": {"uv": [8.75, 0, 7.75, 3], "texture": "#0"} + } + }, + { + "name": "cartridge", + "from": [7, 2, 1], + "to": [9, 8, 5], + "faces": { + "north": {"uv": [11.75, 0, 12.25, 3], "texture": "#0"}, + "east": {"uv": [10.75, 0, 11.75, 3], "texture": "#0"}, + "west": {"uv": [11.75, 0, 10.75, 3], "texture": "#0"} + } + }, + { + "name": "cartridge", + "from": [13, 2, 1], + "to": [15, 8, 5], + "faces": { + "north": {"uv": [10.25, 0, 10.75, 3], "texture": "#0"}, + "east": {"uv": [9.25, 0, 10.25, 3], "texture": "#0"}, + "west": {"uv": [10.25, 0, 9.25, 3], "texture": "#0"} + } + }, + { + "name": "screenframe", + "from": [1.5, 7.3, 1], + "to": [5.5, 11.3, 2], + "rotation": {"angle": 22.5, "axis": "x", "origin": [3.5, 14, 0.5]}, + "faces": { + "east": {"uv": [5, 0, 6, 0.5], "rotation": 90, "texture": "#0"}, + "south": {"uv": [5, 0.5, 6, 2.5], "texture": "#0"}, + "west": {"uv": [5, 0, 6, 0.5], "rotation": 90, "texture": "#0"}, + "up": {"uv": [5, 0, 6, 0.5], "texture": "#0"}, + "down": {"uv": [5, 0, 6, 0.5], "texture": "#0"} + } + }, + { + "name": "screen", + "from": [1.5, 7.3, 1], + "to": [5.5, 11.3, 1], + "rotation": {"angle": 22.5, "axis": "x", "origin": [3.5, 14, 0.5]}, + "faces": { + "north": {"uv": [4, 0, 5, 2], "texture": "#0"} + }, + "forge_data": { + "block_light": 15 + } + }, + { + "from": [1, 2, 1], + "to": [6, 8, 5], + "faces": { + "north": {"uv": [9, 7, 10.25, 10], "texture": "#0"}, + "east": {"uv": [8, 7, 9, 10], "texture": "#0"}, + "west": {"uv": [10.25, 7, 11.25, 10], "texture": "#0"} + } + }, + { + "name": "arm", + "from": [11, 11.5, 7.5], + "to": [12, 18.5, 9.5], + "rotation": {"angle": -45, "axis": "x", "origin": [11.5, 14, 8.5]}, + "faces": { + "north": {"uv": [0, 9.5, 1.75, 10], "rotation": 270, "texture": "#0"}, + "east": {"uv": [0, 10, 1.75, 11], "rotation": 270, "texture": "#0"}, + "south": {"uv": [0, 9.5, 1.75, 10], "rotation": 270, "texture": "#0"}, + "west": {"uv": [0, 11, 1.75, 10], "rotation": 270, "texture": "#0"} + } + }, + { + "name": "arm", + "from": [10.5, 12.54537, 5.01779], + "to": [12.5, 18.54537, 8.01779], + "rotation": {"angle": 22.5, "axis": "x", "origin": [11.5, 18.27582, 6.35928]}, + "faces": { + "north": {"uv": [2.5, 8, 4, 9], "rotation": 270, "texture": "#0"}, + "east": {"uv": [2.5, 9, 4, 10.5], "rotation": 270, "texture": "#0"}, + "south": {"uv": [2.5, 8, 4, 9], "rotation": 270, "texture": "#0"}, + "west": {"uv": [2.5, 9, 4, 10.5], "rotation": 270, "texture": "#0"}, + "up": {"uv": [2, 9.5, 2.5, 11], "texture": "#0"}, + "down": {"uv": [2, 8, 2.5, 9.5], "rotation": 180, "texture": "#0"} + } + }, + { + "name": "baseplate", + "from": [1, 9.5, 1], + "to": [15, 10.5, 8], + "faces": { + "north": {"uv": [8, 6.5, 11.5, 7], "texture": "#0"}, + "east": {"uv": [8, 6.5, 9.75, 7], "texture": "#0"}, + "south": {"uv": [8, 6.5, 11.5, 7], "texture": "#0"}, + "west": {"uv": [9.75, 6.5, 11.5, 7], "texture": "#0"}, + "up": {"uv": [8, 3, 11.5, 6.5], "texture": "#0"} + } + }, + { + "name": "support", + "from": [1, 0, 15], + "to": [5, 8, 16], + "faces": { + "east": {"uv": [13.25, 0, 13.5, 4], "texture": "#0"}, + "south": {"uv": [12.25, 0, 13.25, 4], "texture": "#0"}, + "west": {"uv": [13.25, 0, 13.5, 4], "texture": "#0"}, + "down": {"uv": [12.25, 4, 13.25, 4.5], "texture": "#0"} + } + }, + { + "name": "support", + "from": [11, 0, 15], + "to": [15, 8, 16], + "faces": { + "east": {"uv": [13.25, 0, 13.5, 4], "texture": "#0"}, + "south": {"uv": [12.25, 0, 13.25, 4], "texture": "#0"}, + "west": {"uv": [13.25, 0, 13.5, 4], "texture": "#0"}, + "down": {"uv": [12.25, 4, 13.25, 4.5], "texture": "#0"} + } + }, + { + "name": "mesh", + "from": [0, 10, 0], + "to": [0, 13, 9], + "faces": { + "east": {"uv": [0, 8, 2, 9.5], "texture": "#0"}, + "west": {"uv": [2, 8, 0, 9.5], "texture": "#0"} + } + }, + { + "name": "mesh", + "from": [16, 10, 0], + "to": [16, 13, 9], + "faces": { + "east": {"uv": [0, 8, 2, 9.5], "texture": "#0"}, + "west": {"uv": [2, 8, 0, 9.5], "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "thirdperson_lefthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "firstperson_righthand": { + "rotation": [0, 45, 0], + "scale": [0.4, 0.4, 0.4] + }, + "firstperson_lefthand": { + "rotation": [0, 225, 0], + "scale": [0.4, 0.4, 0.4] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.25, 0.25, 0.25] + }, + "gui": { + "rotation": [30, 225, 0], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/water_source.json b/src/main/resources/assets/overdrive_that_matters/models/block/water_source.json new file mode 100644 index 000000000..3daef1784 --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/models/block/water_source.json @@ -0,0 +1,164 @@ +{ + "credit": "Made with Blockbench", + "render_type": "cutout", + "texture_size": [32, 32], + "textures": { + "0": "overdrive_that_matters:block/water_source_misc", + "1": "overdrive_that_matters:block/water_source", + "2": "overdrive_that_matters:block/water_source_pump", + "particle": "overdrive_that_matters:block/water_source" + }, + "elements": [ + { + "name": "body", + "from": [10, 0, 0], + "to": [16, 16, 9], + "faces": { + "north": {"uv": [0, 0, 3, 8], "texture": "#1"}, + "east": {"uv": [12.5, 8, 8, 16], "texture": "#1"}, + "south": {"uv": [13, 0, 16, 8], "texture": "#0"}, + "west": {"uv": [8, 0, 12.5, 8], "texture": "#1"}, + "up": {"uv": [0, 8, 3, 12.5], "rotation": 180, "texture": "#1"}, + "down": {"uv": [0, 9, 3, 13.5], "rotation": 180, "texture": "#1"} + } + }, + { + "name": "body", + "from": [0, 10, 0], + "to": [10, 16, 9], + "faces": { + "north": {"uv": [3, 0, 8, 3], "texture": "#1"}, + "south": {"uv": [8, 0, 13, 3], "texture": "#0"}, + "west": {"uv": [8, 0, 12.5, 3], "texture": "#1"}, + "up": {"uv": [3, 8, 8, 12.5], "rotation": 180, "texture": "#1"}, + "down": {"uv": [8, 8, 3, 12.5], "texture": "#1"} + } + }, + { + "name": "body", + "from": [0, 0, 0], + "to": [10, 6, 9], + "faces": { + "north": {"uv": [3, 5, 8, 8], "texture": "#1"}, + "south": {"uv": [8, 5, 13, 8], "texture": "#0"}, + "west": {"uv": [8, 5, 12.5, 8], "texture": "#1"}, + "up": {"uv": [3, 8, 8, 12.5], "rotation": 180, "texture": "#1"}, + "down": {"uv": [3, 9, 8, 13.5], "rotation": 180, "texture": "#1"} + } + }, + { + "name": "body", + "from": [0, 6, 5], + "to": [10, 10, 9], + "faces": { + "north": {"uv": [3, 3, 8, 5], "texture": "#1"}, + "south": {"uv": [8, 3, 13, 5], "texture": "#0"}, + "west": {"uv": [10.5, 3, 12.5, 5], "texture": "#1"} + } + }, + { + "name": "pump", + "from": [9, 1, 9], + "to": [15, 14, 15], + "faces": { + "east": {"uv": [0, 0, 3, 6.5], "texture": "#0"}, + "south": {"uv": [6, 0, 12, 13], "texture": "#2"}, + "west": {"uv": [0, 0, 3, 6.5], "texture": "#0"}, + "up": {"uv": [3, 0, 6, 3], "texture": "#0"}, + "down": {"uv": [3, 0, 6, 3], "texture": "#0"} + } + }, + { + "name": "pump", + "from": [1, 1, 9], + "to": [7, 14, 15], + "faces": { + "east": {"uv": [0, 0, 3, 6.5], "texture": "#0"}, + "south": {"uv": [0, 0, 6, 13], "texture": "#2"}, + "west": {"uv": [0, 0, 3, 6.5], "texture": "#0"}, + "up": {"uv": [3, 0, 6, 3], "texture": "#0"}, + "down": {"uv": [3, 0, 6, 3], "texture": "#0"} + } + }, + { + "name": "pump", + "from": [2, 14, 10], + "to": [14, 15, 14], + "faces": { + "north": {"uv": [0, 13.5, 6, 14], "texture": "#1"}, + "east": {"uv": [6, 14, 6.5, 16], "rotation": 90, "texture": "#1"}, + "south": {"uv": [0, 13.5, 6, 14], "texture": "#1"}, + "west": {"uv": [6, 14, 6.5, 16], "rotation": 90, "texture": "#1"}, + "up": {"uv": [0, 14, 6, 16], "texture": "#1"}, + "down": {"uv": [0, 14, 6, 16], "texture": "#1"} + } + }, + { + "name": "mesh", + "from": [0, 0, 9], + "to": [16, 16, 16], + "faces": { + "east": {"uv": [8, 8, 4.5, 16], "texture": "#0"}, + "south": {"uv": [8, 8, 16, 16], "texture": "#0"}, + "west": {"uv": [4.5, 8, 8, 16], "texture": "#0"}, + "up": {"uv": [0, 8, 3.5, 16], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 8, 3.5, 16], "rotation": 90, "texture": "#0"} + } + }, + { + "name": "mesh", + "from": [0, 16, 9], + "to": [16, 0, 16], + "faces": { + "east": {"uv": [8, 8, 4.5, 16], "texture": "#0"}, + "south": {"uv": [8, 8, 16, 16], "texture": "#0"}, + "west": {"uv": [4.5, 8, 8, 16], "texture": "#0"}, + "up": {"uv": [0, 8, 3.5, 16], "rotation": 270, "texture": "#0"}, + "down": {"uv": [0, 8, 3.5, 16], "rotation": 90, "texture": "#0"} + } + }, + { + "name": "body", + "from": [1, 6, 1], + "to": [10, 10, 5], + "faces": { + "north": {"uv": [3, 3, 7.5, 5], "texture": "#1"}, + "west": {"uv": [8.5, 3, 10.5, 5], "texture": "#1"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "thirdperson_lefthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "firstperson_righthand": { + "rotation": [0, 45, 0], + "scale": [0.4, 0.4, 0.4] + }, + "firstperson_lefthand": { + "rotation": [0, 225, 0], + "scale": [0.4, 0.4, 0.4] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.25, 0.25, 0.25] + }, + "gui": { + "rotation": [30, 225, 0], + "scale": [0.625, 0.625, 0.625] + }, + "head": { + "rotation": [0, 180, 0] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/textures/block/painting_table.png b/src/main/resources/assets/overdrive_that_matters/textures/block/painting_table.png new file mode 100644 index 0000000000000000000000000000000000000000..e5c6dc2eedae8af7a6d02d85b2bd4de3b46ee7be GIT binary patch literal 831 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3-p)I`?e@QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`Ljrt4T-DUn{@-Bu|G=}pzCIx#L0elpBqW5P?+nBA8w?9x9%0Bo!%+N$ zq5j4(hWED_{=a1~H8uVJ|G$`+SW!{Y?c2BKnVP0mw&XVT$L3eHx3{mI>jO0SVx2-1 zkdi40@(Ttk#swI}H$A!zRL5E15n0T@z;_6Q8AUa`8W3O=ImaV{rLEN{|}{B&HJb4 zH@sRmn_KaS$fCo~4}Yx4aSZ2KcU_w&;1I*pa|({)!9JX96=_UTUyMBD=Nnm^elVM@ zbBC0M*%g&rB02}NxlC3FtysO9@ruLLjs}4>Yk2ReM?5*iXRERf%wD;=a!Nvok9E&9}xZOV)JO{mx$~>`ia%>ye{T80?Hdkm-*hnj>Mp4>mgydQPh`a|)V%WKj*SO%(d6g* z(sR$Rejgj69LRfKs&A2*5!W8mrS6>_daDk0Nbp^>VAZSZIq$gl@39>cu^Ntd&1?+c z<~^HQ*l@XwPmXkW|dd_!tUocKMC1&+7vp7d^1 z{{HS-17kywvE!RkMZ1F{w~i-0;52jC{3z8yl1EOpvGl`6?y%oZS^+!-Pd+j#{9t$> z+;HOBq6c1ko$hmfo%XEl^ZCQ)*PefWz+#_qg8b_oce|dbCx>1H>+e{n5b8RkKq%(S za!!42Ywo3wcQqYLW#YD(+1NU*kw2y&_Tkz_+kFMGjjLuA#7o~PWGYqoxcE{jtNpXq zxsBg{3tksJv|DidlyiFAciw;7f5YqjcV+MN$y@K*|CXrhOb+s40VXyEPgg&ebxsLQ E0NX}-JOBUy literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/overdrive_that_matters/textures/block/water_source.png b/src/main/resources/assets/overdrive_that_matters/textures/block/water_source.png new file mode 100644 index 0000000000000000000000000000000000000000..d1737a8fd54dfd756a52bbda606ed71a8c288b5a GIT binary patch literal 542 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCilg0(?STwY9ZFLP8P}5{_*N7ZVf9ZR-F3|9@anM zpo4-vT^vI!{8J}&Z);KDaAhpbky$zO|NooS2fWtJmDB4<;1&=x=I-v4Tz1n%^M6~1 zSEb|ADL1z*DY5+Ua>8FN9_dGa3Rc`)_p)I54jHenuYD9JJDxencu}&d;=I zooL*4f&0omnF&msU60taJzuoW|1GxWR@CaohxMXCQo*v%5`WG+&(X+OcyVst>f8r6 z7I5;+m3+Qwa^lgpiWZ=un_WNDB{6?yJZhD2Uv`cBwugL)a@R!a-c-xg?YDoEFRyFf Survu6<_w;$elF{r5}E*R*yK+D literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_mask.png b/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..f1effd65ad0e577ba6de2ecb1657f1dec94eb2d2 GIT binary patch literal 284 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCikh0(?STpFe+o?AWmzH*Nq0*0J8$1X5QLba4!^@V`1Skne~B2kZQz|JM383+_(M68=}_p?k4Ypk)sOqb$qB zk3BI>#~me-3Iz-#q7zTg=a_tG&bObZnq64)bZ(nZFnsg=HS_idB46(;yd-ccd99B1 z){{z4WDFQjcRyf_jC{!v&Z*0w{m_4s&b}nudfv@kfts0j4&*6?OPL>WnB4ZE`2_po Xn_Mp1`q%w{j$-h1^>bP0l+XkKVBBR$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_misc.png b/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_misc.png new file mode 100644 index 0000000000000000000000000000000000000000..4c55238ef41647cf51fe592f32640a07c0b2ebdc GIT binary patch literal 401 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCiji0(?STi;9Zs>+7|(wbj(r+S}VrO-(~WLV%LOrgK$*6h}#rU+{kjV7S-3 zHxekuS>O>_%)r2R7=#&*=dVZs3cmAnaSXBWpBls{bXbAM$m;R`dK&|styk~n-Pj$q zu%mP7jjucluH6#)q4AB0$3{emVedCNW6l%emS0%e9d~m}^)R|!5G!}gmv86UY1z^c zvY?Y|4okhYi^s+T^P`_=9%0(Qy`t?(Rg(7BYr>nI6|StF?66i%qoCaQyWu0>4X--d z-hDXiesF<;+Kjag4X1Nd`kFR!Kl}7lVEUs&d(;f#;?!ecoY2B-oOk@m|CxzW0~++Y6!TJo}q$fIesNboFyt=akR{008TnsQ>@~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png b/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png new file mode 100644 index 0000000000000000000000000000000000000000..d78517297e9723debea5752da26158f5172a0d21 GIT binary patch literal 554 zcmeAS@N?(olHy`uVBq!ia0vp^0t^g{3>?frR&Nhm4Ul3i4sv&5Sa(k5C6L3C?&#~t zz_78O`%fY(kgp!#6XIG_R8(JI-`?J?rluw)CT41C8WIwckdW}7fx$ZQj79W8bE&E zz4cV`EFS*SKQq`(cXMpLIiu%@at5!3hFwK~n84yRY4@j!)rAf1Z-93Gij}*PGkM#m z1sB_zFF7g5324YvoS2frIQim-hR0eqe32$^-Q`MN3Yfgzx%gho5oYD9-26M`t)Dgi zcrw8~+up|K`$vl`nNJqGbo)2IyALwcAxiYavx^@bqEy2!3k5SQD)j!gpmCbK&v**#2bT8@ZTEVwDcw^vn8BKJ|_7Irxm1sP5w h$^43%&woo|<2@h8gsyy5v=A6444$rjF6*2UngC(E=Nte4 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png.mcmeta b/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png.mcmeta new file mode 100644 index 000000000..d0da1eb25 --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "frametime": 2, + "interpolate": true + } +} \ No newline at end of file From 58ed338c7a19927cd63d60e78df78fa99c9d9d91 Mon Sep 17 00:00:00 2001 From: GearShocky Date: Mon, 29 Jan 2024 03:03:39 +0600 Subject: [PATCH 10/38] Various texture updates --- .../textures/item/chest_upgrader.png | Bin 2437 -> 266 bytes .../textures/item/component/electromotor.png | Bin 2437 -> 522 bytes .../item/component/tritanium_ingot.png | Bin 253 -> 257 bytes .../item/resources/tritanium_ore_clump.png | Bin 263 -> 299 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/resources/assets/overdrive_that_matters/textures/item/chest_upgrader.png b/src/main/resources/assets/overdrive_that_matters/textures/item/chest_upgrader.png index d36635b4d3d72a5dd2644f4bd55341d6da866d5b..ebe4faa74eadb2018bf85487238ca08b39b86de5 100644 GIT binary patch delta 244 zcmZn_?qX8x4DfU3<&xrJU|`_&^l%9R(gGmN!3-odboqlPDk{_~2Ka=y{%2s&*4DQ1 z@SnT;OyjH-xlR4C`Bi?g>D%q>=9!uTRj+?!A_}CqOM?7@|HA=;mp|htpfG2FM`SSr z1K)lSX0%`pRsjk|d%8G=XavWeiRL??z~OR{$!qFg{T)2~$yOg1e{cD+(fI$F>x(PA zSYxsiCK^5qS;{g^^78h?wY_;C_#D|6$Ub5aU}yN!xVG}a0q6B>55C`MJd?%#t2t0t ds^I(^=KIp@&T^uUZUOCK@O1TaS?83{1ON&XSE>L2 delta 2432 zcmV-`34ivA0)-PHiBL{Q4GJ0x0000DNk~Le0000W0000W2m$~A0Q?y3qmdyXe+h6% zS#tmY4!{5a4!{9w)`zZJjkY>wb;}+i^bu_gMVX#MEe?A$v*Na(MM4QcKvNOrc zVt#pbv5sJ!F;>@gp66QYx>Ssko*|F+b~vfvjo)&zJV}yR)rwHAdF9Y#e=9J0gTAr@ zH)yX@#d@8fNU|s29e2Vu&SY6CxO_G}Rf^zIO2Kvf#!Z}3-{SXPyt}%bQ%d|+3tK9s zYfUNTRB)S1-?d!FF7bjJhzy=F&-0SJ==AzOJUbZwv<+sO=GpoAcxSKM>Bn&l zC_erC;cPZ1gx0$84G&PlV@rMa_I{q1Cl}|sCWdKHgjrXDQ&}Uie3t^a!=ZQk=qH}rKEJqtoB#aRCyR9gJbL}!<@Ex{ zfJIF<2x$kw>Dk%r8krNSX0~YpAIq_eB9Ee!(Ha2NH3M#oWyB3*dUE>Z*Z*O+j_%B6 zvvANd4C~qSY#m3VfAJW=7eyfi(m-&EGQ~w*sA>^s8Q2OBYrvyxN|wuYr9e?&ML97l zt*TO`X?%SAG)gvUq4@89^NwTtzyK)y+8Bo;<(=%B7aGmAs;pFk_@iEC*WyFp>51W&NQzpQa7f- zku1yb1;hhne`#5moG{<_vHHzdU-_QdYdN9glz^!yuU9GRF3sZg^}>?+&i=sl`FuVb zj|K-j+oH&1oj4K>Da$krA@RX}R8?Koy3|Mts??H+6e$pM9!x)eb_(b#31_ zObem}Xi)-E8ohSwjn`hN^JJ?(^aAhU7hkkOKlJ_Wf9*kDD#vsb3c9M0cHoKX!A+7= z+>27-AH08m`u(>p*B*r7{A&K>*=a`PaS4+Y;QhaN7>)l^I@H{iiV-(%;Vh)tumYZe;vYD4O z&lFU*$dWA2fNG~5T2ymgwnGnb@PmPbGnUEHe=IjmHl1C>Inh)>04}c9wJL}G&Rh52 z0A~zSY*uT_u)LO^7WsUgetUX3y;@x@mYkC;-!NtxASWk-w&y`wYvrLi_`WL*PHG+m zodObJImgqJ>GkHv`3AL3h1lKQ&$BA4;L#9DZrjf6eE#V8`+tA&==^w7O|Q88^LF@8ID1qdRv8-9ayCyJ$zGoQy{=-+M7h zV~AR&Rd2MtxLo9E5rn;(K=-Azd%fZA)zzZi^7p#I!4`nwd6cAS8U$_A^!R%Zei62O z!?HD_Uf92N=jgRpUfJE7kUV>E|BZJaf4mKRQU4$-;_y7@@mJqCmiz7F$2$jyagv}L z=saUYO-B8G+YUU-6wGtM9%|dJW!wCnH-F~(es^mSc0rs@(CYO2-SM#Z@=srotVWi? z0F3v9Fj1$-XrgF=a zf)mGTioviN>BSaT@2FXY^$@OX}UAr?J5J|b= zI9?F=t+Ys2i%Y1I;FuB!+%<5$f8&5gMHca2|LS$LJzAG|2R(sl&-e2p2d}O!&Uus> zS&8Y0Gk%VRC5|ifooK|KPnh8|jb& zuQ?YCs?K;6ML??;29F+o<|tUNQeDg!S6&FQ^5Zl%g+O!W=#I3qOzz?=f1}dyOxpvq zi?XT-N#g|Vn!oq^J7h6TonID#4y4khW)cmP2`LN{ zXPZS`gT_!UDs5@FOjTINa3+xIn`}3YiGXv!@@6RVFjCrK(CZLOP=E;ytBbr$DqX-8 z3?JCjLJbWE zZEYId5V*7z2n|gUs7uq~(9+T%gwqK+DQz~nG&FSaeRsd(uFL$ukN57+_xs-a@n{~J zrUmVkTCLWCojL^UIFocbZQ3a_e;f`yntu(-<+52chm;9NXk%-a%-jma_fKgunK-(c z1`tQ1QA#G0{5&3yX*!)!yC~CA?bb1I=5vF#QTgPnPnYo!)ppicY#0XRt{heM3QI4xr@PIzz0hrj{VsKD!(Xs{^r?(eBOH5?RI?&2E^P4 knHX(8{{7EfL}d%29|k6;f~n?p^Z)<=07*qoM6N<$g6eqMTmS$7 delta 2424 zcmV-;35WKI1cehJiBL{Q4GJ0x0000DNk~Le0000W0000W2m$~A0Q?y3qmdyff4~3$ z4!{9w)`zZJjkY>wb;}+i^bu_gMVX#MEe?A$v*Na(MM4QcKvNOrcVt#pbv5sJ! zF;>@gp66QYx>Ssko*|F+b~vfvjo)&zJV}yR)rwHAdF9Y#D=>P4zOn;1e`v2$#d@8f zNU|s29e2Vu&SY6CxO_G}Rf^zIO2Kvf#!Z}3-{SXPyt}%bQ%d|+3tK9sYfUNTRB)S1 z-?d!FF7bjJhzy=F&-0SJ==AzOJUbZwv<+sO=GpoAcxSKM>Bn&lC_erC;cPZ1 zgx0$84G&PlV@rMa_I{q1Cl}|sCWdKHgjrXDQ&)De+fce_dZIm_&3^42FFG zSgLBdK|Tmpe>}Uie3t^a!=ZQk=qH}rKEJqtoB#aRCyR9gJbL}!<@Ex{fJIF<2x$kw z>Dk%r8krNSX0~YpAIq_eB9Ee!(Ha2NH3M#oWyB3*dUE>Z*Z*O+j_%B6vvANd4C~qS zY#m3V@fg4tMIi*ze?V}GGQ~w*sA>^s8Q2OBYrvyxN|wuYr9e?&ML97lt*TO`X?%SA zG)gvUq4@89^NwTtzyK)y+8Bo;<(=% zB7aGmAs;pFk_@iEC*WyFp>51W&NQzpQa7f-ku1yb1;hhn zX<3+@FyHsFfBMZ=U-_QdYdN9glz^!yuU9GRF3sZg^}>?+&i=sl`FuVbj|K-j+oH&1 zoj4K>Da$krA@RX}R8?Koy3|Mts??H+6e$pM9!x)eb_(b#31_Obem}Xi)-E z8ohSwjn`hN^JJ?(^aAhU7hkkOKlJ_W?Ll5D$8;15f4ZuWcHoKX!A+7=+>27-AH08m z`u(>p*B*r7{A&K>*=a`PaS4+Y;QhaN7>)l^I@H{iiV-(%;Vh)tumYZe;vYD4O&lFU*$dWA2 zfNG~5T2ymgwnGnb@PmPbGnUEHEH_Oyon6E^f6-Jy04}c9wJL}G&Rh520A~zSY*uT_ zu)LO^7WsUgetUX3y;@x@mYkC;-!NtxASWk-w&y`wYvrLi_`WL*PHG+modObJImgqJ z>GkHv`3AL3h1lKQ&$BA4;L#9DZrjf6eE#V8`+tA&o?oEcnj>==^w7O|Q88^LF@8ID1qdRv8-9ayCyJ$zGoQy{=-+M7hV~AR&Rd2Mt zxLo9E5rn;(K=-Azd%fZA)zzZi^7p#I!4`nwd6cAS8U$_A^!R%Zei62O!?HD_Uf92N z=jgRpUfJE7kUV>E|BZJaybXL&{~#;kfABo#@mJqCmiz7F$2$jyagv}L=saUYO-B8G z+YUU-6wGtM9%|dJW!wCnH-F~(es^mSc0rs@(CYO2-SM#Z@=srotVWi?0F3v9Fj1$- zXrgF=af)mGTioviN z>BSaT@2FXY^$@OX}UAr?J5J|b=I9?F=t+Ys2 zi%Y1I;FuB!+%<5$S&8Y0Gk%VRC5|ifooK|KPnh8|jb&uQ?YCs?K;6 zML??;29F+o<|tUNQeDg!S6&FQ^5Zl%g+O!W=#I3qOzz?=qtft9+XJ(Uf3m6xN#g|V zn!oq^J7h6TonID#4yCVu1P9tn#fB`$O4}LTgEP^mi$MaBQ00f}p$CF&;8&yQQYQ}7oJ_kUi02apcrR?M`SSr z1K$A}u?QuLe)n3tdy?|io z;}4VC-7k2QKh({*p{V>pDocuMk=p-P=N22E$!g)7nb@Ln_2{W5)3O2=%&|_G=9chP gXw&lgokuMBTf$jRu-eEL0Ig#1boFyt=akR{0NHm;(*OVf delta 182 zcmZo<`pY=MzrJzSin+VbXlrZ7=2tN=Fa*3Xj|Wm5B|(0{{~>_kUi02apcrR?M`SSr z1K&XqX529``z=r~%G1R$L?gJi&r^s&k>iL|%FqA(%LP9^NGwv?=;dJdhxJV*6NBK| z#GHv*JHj?Fl(o#zefn85Oe?N_M3=VQ&@Jyt~UGyw1&ac)z4*}Q$iB}-X2JC diff --git a/src/main/resources/assets/overdrive_that_matters/textures/item/resources/tritanium_ore_clump.png b/src/main/resources/assets/overdrive_that_matters/textures/item/resources/tritanium_ore_clump.png index 7e121ec3799284928d206589d1372e66453baddd..b7f21ffc20cdc180f9537b6b0481d1839ba9088f 100644 GIT binary patch delta 242 zcmZo?TFo@Uv0gF2C&bmp!#}sFf9{!0^-DV&XRVmK`%G?MrM9-VUu?Q>S|S4j1NY-> zeGpX=FD;G z|C_pZ<}MGelj&>JcL@#PywbrNh3%go{C^ZmFd>HV~K hFZ<>GF^4_h!{89fma93{@Gj6H44$rjF6*2UngEaFV~zj- delta 206 zcmZ3@)Xp@)v0gO5C&bmp!#}sFf9~!xjk8v0Yis+(rZX@wEaYVP52V;jg8YL2g8_q- zH?td1h_k>WvY3H^Z$Ah#TCfJI00lEVT^vI+f@Axl`HmQH9I3ef|AcJwuBg⁡U;3 z&Z^rdw)}SO_Yhxe&@Ez>7T-Ea^P7`QyRbXU-7C@0TRIqZ^Eibs-CZKU6Mv`QTQ|w) zP)F1iX0F}~6{fEbdG{>X61R5$RsHAxS!Px;JdtAF&bPPcG0;*5Pgg&ebxsLQ09(RO AUH||9 From a885ea4d87e93fc9d321b42149de17332730d370 Mon Sep 17 00:00:00 2001 From: GearShocky Date: Mon, 29 Jan 2024 04:15:13 +0600 Subject: [PATCH 11/38] Models and more texture updates --- .../mc/otm/datagen/blocks/BlockStates.kt | 3 ++ .../mc/otm/datagen/items/ItemModels.kt | 3 ++ ...source.json => infinite_water_source.json} | 0 .../{painting_table.json => painter.json} | 0 .../models/item/matter_cable.json | 50 ------------------ .../resource/deepslate_tritanium_ore.png | Bin 283 -> 312 bytes .../textures/block/resource/tritanium_ore.png | Bin 285 -> 303 bytes 7 files changed, 6 insertions(+), 50 deletions(-) rename src/main/resources/assets/overdrive_that_matters/models/block/{water_source.json => infinite_water_source.json} (100%) rename src/main/resources/assets/overdrive_that_matters/models/block/{painting_table.json => painter.json} (100%) delete mode 100644 src/main/resources/assets/overdrive_that_matters/models/item/matter_cable.json diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockStates.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockStates.kt index 68846f7b9..8cf6bd9b6 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockStates.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/BlockStates.kt @@ -114,6 +114,9 @@ fun addBlockStates(provider: MatteryBlockStateProvider) { provider.block(MBlocks.ENERGY_SERVO.values) provider.block(MBlocks.COBBLESTONE_GENERATOR.values) + provider.block(MBlocks.PAINTER) + provider.block(MBlocks.INFINITE_WATER_SOURCE) + provider.exec { for (block in MBlocks.ESSENCE_STORAGE.values) { provider.getVariantBuilder(block).forAllStates { diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt index daadb672c..349820416 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/ItemModels.kt @@ -186,6 +186,9 @@ fun addItemModels(provider: MatteryItemModelProvider) { provider.coloredWithBaseBlock(MItems.MATTER_RECYCLER, "matter_recycler", "_idle") provider.coloredWithBaseBlock(MItems.COBBLESTONE_GENERATOR, "cobblestone_generator") + provider.block(MItems.PAINTER, "painter") + provider.block(MItems.INFINITE_WATER_SOURCE, "infinite_water_source") + provider.exec { provider.withExistingParent("essence_storage", modLocation("block/essence_storage_empty")) .override() diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/water_source.json b/src/main/resources/assets/overdrive_that_matters/models/block/infinite_water_source.json similarity index 100% rename from src/main/resources/assets/overdrive_that_matters/models/block/water_source.json rename to src/main/resources/assets/overdrive_that_matters/models/block/infinite_water_source.json diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/painting_table.json b/src/main/resources/assets/overdrive_that_matters/models/block/painter.json similarity index 100% rename from src/main/resources/assets/overdrive_that_matters/models/block/painting_table.json rename to src/main/resources/assets/overdrive_that_matters/models/block/painter.json diff --git a/src/main/resources/assets/overdrive_that_matters/models/item/matter_cable.json b/src/main/resources/assets/overdrive_that_matters/models/item/matter_cable.json deleted file mode 100644 index 530e26553..000000000 --- a/src/main/resources/assets/overdrive_that_matters/models/item/matter_cable.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "parent": "block/block", - "texture_size": [16, 16], - "textures": { - "0": "overdrive_that_matters:block/matter_cable", - "particle": "#0" - }, - "elements": [ - { - "from": [6, 6, 6], - "to": [10, 10, 10], - "faces": { - "north": {"uv": [0, 0, 4, 4], "texture": "#0"}, - "south": {"uv": [0, 0, 4, 4], "texture": "#0"}, - "up": {"uv": [0, 0, 4, 4], "texture": "#0"}, - "down": {"uv": [0, 0, 4, 4], "texture": "#0"} - } - }, - { - "from": [0, 6, 6], - "to": [6, 10, 10], - "faces": { - "north": {"uv": [4, 0, 10, 4], "texture": "#0"}, - "south": {"uv": [10, 0, 4, 4], "texture": "#0"}, - "west": {"uv": [0, 0, 4, 4], "texture": "#0"}, - "up": {"uv": [10, 0, 4, 4], "texture": "#0"}, - "down": {"uv": [10, 0, 4, 4], "texture": "#0"} - } - }, - { - "from": [10, 6, 6], - "to": [16, 10, 10], - "faces": { - "north": {"uv": [10, 0, 16, 4], "texture": "#0"}, - "east": {"uv": [0, 0, 4, 4], "texture": "#0"}, - "south": {"uv": [16, 0, 10, 4], "texture": "#0"}, - "up": {"uv": [16, 0, 10, 4], "texture": "#0"}, - "down": {"uv": [16, 0, 10, 4], "texture": "#0"} - } - } - ], - "gui_light": "front", - "display": { - "gui": { - "rotation": [0, 0, 0], - "translation": [0, 0, 0], - "scale": [1, 1, 1] - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/overdrive_that_matters/textures/block/resource/deepslate_tritanium_ore.png b/src/main/resources/assets/overdrive_that_matters/textures/block/resource/deepslate_tritanium_ore.png index 1cff8f4670747feb3f2dcc59752182040481b240..786132f8bd80ddc8e4cf2b0c6daa61388c936f73 100644 GIT binary patch delta 255 zcmV0$PflHDox99|ny5`?VQr3i zZGw-T%(8!_iTfo%4FCWD32;bRa{vGizW@LZzX3P}QzQTY0GCNbK~xyiV_;NLG8Pn4 zR$@?gF%DByGFD~~WE4toaW*k#FcO`tVaOmT#NZsZ+E_GAPzZKJEoDIlW6ec^YKvWr85o3&O_Yoj1%M186$L>hK>&`KACBG7;hg{g002ovPDHLk FV1f~(VC?_^ delta 226 zcmV<803H9h0-FMmL4O`lOjJdAd3j`HWKmI3Jv~D&FE?$1k6mwiJV;MYU1v2lH3vgX zr~m)}32;bRa{vGizW@LZzX3P}QzQTY0ES6KK~xyi4a+eOf3pSX4;ApY*;9-!2pu}!mh@y cj|cMf2Ug-6IQTjhGynhq07*qoM6N<$g3Df60{{R3 diff --git a/src/main/resources/assets/overdrive_that_matters/textures/block/resource/tritanium_ore.png b/src/main/resources/assets/overdrive_that_matters/textures/block/resource/tritanium_ore.png index 53a1f0e06ec0c70ecaca97e0905cfb8cfce08ec1..b8ad6556b1732e6369f12f84cfc51303748b7d6d 100644 GIT binary patch delta 246 zcmVMSL{lR{)ru|?NN#nj ze;FQ2Pcdk9b;&9u;(E*R{^_A*=cDdISaF}aMhOfy$s(tKfknGGx?xr=i^FNsg7qU@ wzegT&eo6DmGGN|I(c4c_rPE)6q{V^o3%?;5HdZ`J!vFvP07*qoM6N<$f>6C?(f|Me delta 208 zcmV;>05AWq0-XYoK_?ziOjJdWkB@(Ue{^(oXlQ6$TwHB}k6mwiJV;MYU1v2lHR~Of zs*!ORe~3v$K~xyi70xjZf-o2c(2s;L^ZkUqEncA5#967q187fRDkGvv!{`K~-dJ7V z^Z Date: Mon, 29 Jan 2024 11:44:47 +0600 Subject: [PATCH 12/38] Fuck interpolation --- .../textures/block/water_source_pump.png.mcmeta | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png.mcmeta b/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png.mcmeta index d0da1eb25..55c29419e 100644 --- a/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png.mcmeta +++ b/src/main/resources/assets/overdrive_that_matters/textures/block/water_source_pump.png.mcmeta @@ -1,6 +1 @@ -{ - "animation": { - "frametime": 2, - "interpolate": true - } -} \ No newline at end of file +{ "animation": { "frametime": 2 } } \ No newline at end of file From 2930ca8841e339b0d1cd39d58564bcdf8ca9a279 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Mon, 29 Jan 2024 15:28:06 +0700 Subject: [PATCH 13/38] Bump default max energy config value of energy sword to match capacitor battery --- .../kotlin/ru/dbotthepony/mc/otm/item/weapon/EnergySwordItem.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/EnergySwordItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/EnergySwordItem.kt index b641267cb..072273f12 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/EnergySwordItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/EnergySwordItem.kt @@ -223,7 +223,7 @@ class EnergySwordItem : MatteryItem(Properties().stacksTo(1).rarity(Rarity.RARE) fun registerConfig(builder: ForgeConfigSpec.Builder) { builder.comment("Energy sword values").push("EnergySword") - _MAX_ENERGY = builder.defineDecimal("MAX_ENERGY", Decimal(500_000), Decimal.ZERO) + _MAX_ENERGY = builder.defineDecimal("MAX_ENERGY", Decimal(2_000_000), Decimal.ZERO) _ENERGY_ZAP = builder.comment("Extra energy required when hitting androids").defineDecimal("ENERGY_ZAP", Decimal(4_000), Decimal.ZERO) _ENERGY_ZAP_VARIANCE = builder.comment("Random deviation from ENERGY_ZAP").defineDecimal("ENERGY_ZAP_VARIANCE", Decimal(800), Decimal.ZERO) _ENERGY_PER_SWING = builder.defineDecimal("ENERGY_PER_SWING", Decimal(2_000), Decimal.ZERO) From c5b987c2deb4164cb56b219dc1f554f1f0dfb33d Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Mon, 29 Jan 2024 15:28:27 +0700 Subject: [PATCH 14/38] Slightly buff dense battery throughput --- src/main/kotlin/ru/dbotthepony/mc/otm/config/ItemsConfig.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 aa6c8cbc4..7d11124b2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/ItemsConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/ItemsConfig.kt @@ -13,7 +13,7 @@ object ItemsConfig : AbstractConfig("items") { val CRUDE = batteryValues(MNames.BATTERY_CRUDE, Decimal(100_000), Decimal(160), Decimal(40), Decimal(80_000)) val BASIC = batteryValues(MNames.BATTERY_BASIC, Decimal(400_000), Decimal(600)) val NORMAL = batteryValues(MNames.BATTERY_NORMAL, Decimal(2_000_000), Decimal(1_000)) - val DENSE = batteryValues(MNames.BATTERY_DENSE, Decimal(10_000_000), Decimal(2_000)) + val DENSE = batteryValues(MNames.BATTERY_DENSE, Decimal(10_000_000), Decimal(2_500)) val CAPACITOR = batteryValues(MNames.BATTERY_CAPACITOR, Decimal(2_000_000), Decimal(50_000)) val QUANTUM_BATTERY = conciseValues(MNames.QUANTUM_BATTERY, Decimal(40_000_000), Decimal(10_000)) From 308240ac5bd66fd7391d5cf1c38c39bfe11d27da Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Mon, 29 Jan 2024 16:46:46 +0700 Subject: [PATCH 15/38] MatterProviders/MatterConsumers handler filter --- .../mc/otm/container/HandlerFilter.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/HandlerFilter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/HandlerFilter.kt index 12647683a..eadb8a8e0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/HandlerFilter.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/HandlerFilter.kt @@ -6,6 +6,7 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.fluid.stream import ru.dbotthepony.mc.otm.core.isNotEmpty +import ru.dbotthepony.mc.otm.core.math.Decimal interface HandlerFilter { fun canInsert(slot: Int, stack: ItemStack): Boolean { @@ -122,4 +123,32 @@ interface HandlerFilter { return stack.getCapability(MatteryCapability.PATTERN).isPresent } } + + object MatterProviders : HandlerFilter { + override fun canInsert(slot: Int, stack: ItemStack): Boolean { + return stack.getCapability(MatteryCapability.MATTER) + .map { it.matterFlow.output && it.extractMatterChecked(Decimal.POSITIVE_INFINITY, true) > Decimal.ZERO } + .orElse(false) + } + + override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean { + return stack.getCapability(MatteryCapability.MATTER) + .map { !it.matterFlow.output || it.extractMatterChecked(Decimal.POSITIVE_INFINITY, true) <= Decimal.ZERO } + .orElse(true) + } + } + + object MatterConsumers : HandlerFilter { + override fun canInsert(slot: Int, stack: ItemStack): Boolean { + return stack.getCapability(MatteryCapability.MATTER) + .map { it.matterFlow.input && it.receiveMatterChecked(Decimal.POSITIVE_INFINITY, true) > Decimal.ZERO } + .orElse(false) + } + + override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean { + return stack.getCapability(MatteryCapability.MATTER) + .map { !it.matterFlow.input || it.receiveMatterChecked(Decimal.POSITIVE_INFINITY, true) <= Decimal.ZERO } + .orElse(true) + } + } } From 7d4d718b1e2f082e94ee09d004835d1307fb7737 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Tue, 30 Jan 2024 17:45:17 +0700 Subject: [PATCH 16/38] Global block/state tag, additional predicates for multiblock tests, more multiblock performance improvements --- .../ru/dbotthepony/mc/otm/core/Multiblock.kt | 200 ++++++++++++++---- 1 file changed, 157 insertions(+), 43 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt index f908f54f5..783722ae3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt @@ -2,10 +2,16 @@ package ru.dbotthepony.mc.otm.core import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableSet +import it.unimi.dsi.fastutil.objects.Object2IntMap +import it.unimi.dsi.fastutil.objects.Object2IntMaps import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.ObjectArraySet +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import it.unimi.dsi.fastutil.objects.ObjectSets +import it.unimi.dsi.fastutil.objects.Reference2IntMap +import it.unimi.dsi.fastutil.objects.Reference2IntMaps import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap import net.minecraft.core.BlockPos import net.minecraft.core.Direction @@ -20,6 +26,7 @@ import net.minecraft.world.level.block.Rotation import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.chunk.ChunkStatus +import ru.dbotthepony.mc.otm.core.collect.SupplierList import ru.dbotthepony.mc.otm.core.collect.WeakHashSet import ru.dbotthepony.mc.otm.core.collect.collect import ru.dbotthepony.mc.otm.core.collect.map @@ -40,6 +47,10 @@ fun onBlockEntityInvalidated(blockEntity: BlockEntity) { fun interface BlockPredicate { fun test(pos: BlockPos, access: LevelAccessor): Boolean + fun rotate(rotation: Rotation): BlockPredicate { + return this + } + fun and(other: BlockPredicate): BlockPredicate { return BlockPredicate { pos, access -> test(pos, access) && other.test(pos, access) } } @@ -107,13 +118,15 @@ inline fun multiblockEntity(): MultiblockBuilder.Entit return MultiblockBuilder.EntityTag(T::class) } +private val GLOBAL_BLOCK_TAG = Any() + class MultiblockBuilder { private val nodes = Object2ObjectOpenHashMap() + private val customChecks = ArrayList>() - // not data classes to allow having multiple tags with same target - class EntityTag(val clazz: KClass) : Predicate { + class EntityTag(val clazz: KClass, val predicate: Predicate = Predicate { true }) : Predicate { override fun test(t: BlockEntity): Boolean { - return clazz.isInstance(t) + return clazz.isInstance(t) && predicate.test(t as T) } } @@ -121,11 +134,19 @@ class MultiblockBuilder { OR, AND } + fun customCheck(predicate: Predicate): MultiblockBuilder { + customChecks.add(predicate) + return this + } + @Suppress("unchecked_cast") - abstract class Part> { + abstract inner class Part> { val predicates = ObjectArraySet() val children = ObjectArraySet>() + val builder: MultiblockBuilder + get() = this@MultiblockBuilder + val blockStateTags = ObjectArraySet() val blockTags = ObjectArraySet() val blockEntityTags = ObjectArraySet>() @@ -135,11 +156,21 @@ class MultiblockBuilder { return this as T } + fun tagBlockState(): T { + blockStateTags.add(GLOBAL_BLOCK_TAG) + return this as T + } + fun tagBlock(value: Any): T { blockTags.add(value) return this as T } + fun tagBlock(): T { + blockTags.add(GLOBAL_BLOCK_TAG) + return this as T + } + fun tag(value: EntityTag<*>): T { blockEntityTags.add(value) return this as T @@ -216,7 +247,7 @@ class MultiblockBuilder { abstract val strategy: Strategy } - class And

>(val parent: P) : Part>() { + inner class And

>(val parent: P) : Part>() { init { parent.children.add(this) } @@ -227,7 +258,7 @@ class MultiblockBuilder { get() = Strategy.AND } - class Or

>(val parent: P) : Part>() { + inner class Or

>(val parent: P) : Part>() { init { parent.children.add(this) } @@ -258,6 +289,18 @@ class MultiblockBuilder { return relative(dir.default) } + fun relative(diff: Vec3i, configurator: Node.() -> Unit): Node { + return node(pos + diff).also(configurator) + } + + fun relative(dir: Direction, configurator: Node.() -> Unit): Node { + return relative(dir.normal).also(configurator) + } + + fun relative(dir: RelativeSide, configurator: Node.() -> Unit): Node { + return relative(dir.default).also(configurator) + } + fun front() = relative(RelativeSide.FRONT) fun back() = relative(RelativeSide.BACK) fun left() = relative(RelativeSide.LEFT) @@ -341,11 +384,11 @@ class MultiblockBuilder { } fun build(): MultiblockFactory { - return MultiblockFactory(nodes.values.iterator().map { it.build() }.collect(ImmutableSet.toImmutableSet())) + return MultiblockFactory(nodes.values.iterator().map { it.build() }.collect(ImmutableSet.toImmutableSet()), ImmutableList.copyOf(customChecks)) } } -class MultiblockFactory(val north: ImmutableSet) { +class MultiblockFactory(val north: ImmutableSet, val customChecks: ImmutableList>) { data class Part( val pos: BlockPos, val strategy: MultiblockBuilder.Strategy, @@ -357,13 +400,7 @@ class MultiblockFactory(val north: ImmutableSet) { ) fun create(pos: BlockPos): Multiblock { - return Multiblock( - pos, - north, - south, - west, - east, - ) + return Multiblock(pos, this) } val south: ImmutableSet = north.iterator().map { it.copy(pos = it.pos.rotate(Rotation.CLOCKWISE_180)) }.collect(ImmutableSet.toImmutableSet()) @@ -371,22 +408,22 @@ class MultiblockFactory(val north: ImmutableSet) { val east: ImmutableSet = north.iterator().map { it.copy(pos = it.pos.rotate(Rotation.CLOCKWISE_90)) }.collect(ImmutableSet.toImmutableSet()) } -class Multiblock( - pos: BlockPos, - north: Collection, - south: Collection, - west: Collection, - east: Collection, -) { +class Multiblock(pos: BlockPos, factory: MultiblockFactory) { var isValid = false private set - private val configurations = ArrayList() + private val customChecks = factory.customChecks + private var collectFailedParts = false + private val north by lazy(LazyThreadSafetyMode.NONE) { Config(Direction.NORTH, pos, factory.north) } + private val south by lazy(LazyThreadSafetyMode.NONE) { Config(Direction.SOUTH, pos, factory.south) } + private val west by lazy(LazyThreadSafetyMode.NONE) { Config(Direction.WEST, pos, factory.west) } + private val east by lazy(LazyThreadSafetyMode.NONE) { Config(Direction.EAST, pos, factory.east) } + private val configurations = SupplierList(::north, ::south, ::west, ::east) private inner class BEList(val tag: MultiblockBuilder.EntityTag) { val list = ArrayList() val set = ObjectArraySet() - val setView: Set = Collections.unmodifiableSet(set) + val setView: Set = ObjectSets.unmodifiable(set) fun add(blockEntity: BlockEntity) { if (tag.test(blockEntity)) { @@ -453,9 +490,9 @@ class Multiblock( private var blockEntity: BlockEntity? = null private var blockState: BlockState? = null private val assignedBlockEntityLists = ArrayList>(prototype.blockEntityTags.size) - private val assignedBlockStateLists = ArrayList>() - private val assignedBlockLists = ArrayList>() - private val children: ImmutableList = prototype.children.stream().map { Part(pos, it) }.collect(ImmutableList.toImmutableList()) + private val assignedBlockStateLists = ArrayList>() + private val assignedBlockLists = ArrayList>() + private val children: ImmutableList by lazy(LazyThreadSafetyMode.NONE) { prototype.children.stream().map { Part(pos, it) }.collect(ImmutableList.toImmutableList()) } override fun compareTo(other: Part): Int { val cmp = SectionPos.blockToSectionCoord(pos.x).compareTo(SectionPos.blockToSectionCoord(other.pos.x)) @@ -465,15 +502,15 @@ class Multiblock( init { prototype.blockEntityTags.forEach { - assignedBlockEntityLists.add(tag2BlockEntity.computeIfAbsent(it, Object2ObjectFunction { _ -> BEList(it as MultiblockBuilder.EntityTag).also { blockEntityLists.add(it) } })) + assignedBlockEntityLists.add(getBlockEntityList(it)) } prototype.blockStateTags.forEach { - assignedBlockStateLists.add(tag2BlockState.computeIfAbsent(it, Object2ObjectFunction { Reference2IntOpenHashMap().also { blockStateLists.add(it) } })) + assignedBlockStateLists.add(getBlockStateList(it)) } prototype.blockTags.forEach { - assignedBlockLists.add(tag2Block.computeIfAbsent(it, Object2ObjectFunction { Object2IntOpenHashMap().also { blockLists.add(it) } })) + assignedBlockLists.add(getBlockList(it)) } } @@ -609,13 +646,59 @@ class Multiblock( } } + private fun getBlockEntityList(tag: MultiblockBuilder.EntityTag): BEList { + val existing = tag2BlockEntity[tag] + + if (existing != null) + return existing as BEList + + val new = BEList(tag) + blockEntityLists.add(new) + tag2BlockEntity[tag] = new + return new + } + + private fun getBlockList(tag: Any): Reference2IntMap { + val existing = tag2Block[tag] + + if (existing != null) + return existing + + val new = Reference2IntOpenHashMap() + tag2Block[tag] = new + tag2BlockViews[tag] = Reference2IntMaps.unmodifiable(new) + blockLists.add(new) + return new + } + + private fun getBlockStateList(tag: Any): Reference2IntMap { + val existing = tag2BlockState[tag] + + if (existing != null) + return existing + + val new = Reference2IntOpenHashMap() + tag2BlockState[tag] = new + tag2BlockStateViews[tag] = Reference2IntMaps.unmodifiable(new) + blockStateLists.add(new) + return new + } + private val tag2BlockEntity = Object2ObjectOpenHashMap, BEList<*>>() - private val tag2BlockState = Object2ObjectOpenHashMap>() - private val tag2Block = Object2ObjectOpenHashMap>() + private val tag2BlockState = Object2ObjectOpenHashMap>() + private val tag2Block = Object2ObjectOpenHashMap>() + + private val tag2BlockStateViews = Object2ObjectOpenHashMap>() + private val tag2BlockViews = Object2ObjectOpenHashMap>() private val blockEntityLists = ArrayList>() - private val blockStateLists = ArrayList>() - private val blockLists = ArrayList>() + private val blockStateLists = ArrayList>() + private val blockLists = ArrayList>() + + private val globalBlocks = getBlockList(GLOBAL_BLOCK_TAG) + private val globalBlockStates = getBlockStateList(GLOBAL_BLOCK_TAG) + private val globalBlocksView = tag2BlockViews[GLOBAL_BLOCK_TAG]!! + private val globalBlockStatesView = tag2BlockStateViews[GLOBAL_BLOCK_TAG]!! private val parts: ImmutableList = parts.stream() .map { Part(it.pos + pos, it) } @@ -647,6 +730,22 @@ class Multiblock( return (tag2BlockEntity[tag]?.setView ?: setOf()) as Set } + fun blocks(tag: Any): Reference2IntMap { + return tag2BlockViews[tag] ?: Reference2IntMaps.emptyMap() + } + + fun blockStates(tag: Any): Reference2IntMap { + return tag2BlockStateViews[tag] ?: Reference2IntMaps.emptyMap() + } + + fun blocks(): Reference2IntMap { + return globalBlocksView + } + + fun blockStates(): Reference2IntMap { + return globalBlockStatesView + } + fun blockEntityRemoved(blockEntity: BlockEntity): Boolean { var any = false @@ -658,11 +757,6 @@ class Multiblock( } } - private val north = Config(Direction.NORTH, pos, north).also { configurations.add(it) } - private val south = Config(Direction.SOUTH, pos, south).also { configurations.add(it) } - private val west = Config(Direction.WEST, pos, west).also { configurations.add(it) } - private val east = Config(Direction.EAST, pos, east).also { configurations.add(it) } - private var activeConfig: Config? = null val currentDirection: Direction? @@ -673,6 +767,26 @@ class Multiblock( return activeConfig?.blockEntities(tag) ?: setOf() } + fun blocks(tag: Any): Reference2IntMap { + if (!isValid) return Reference2IntMaps.emptyMap() + return activeConfig?.blocks(tag) ?: Reference2IntMaps.emptyMap() + } + + fun blockStates(tag: Any): Reference2IntMap { + if (!isValid) return Reference2IntMaps.emptyMap() + return activeConfig?.blockStates(tag) ?: Reference2IntMaps.emptyMap() + } + + fun blocks(): Reference2IntMap { + if (!isValid) return Reference2IntMaps.emptyMap() + return activeConfig?.blocks() ?: Reference2IntMaps.emptyMap() + } + + fun blockStates(): Reference2IntMap { + if (!isValid) return Reference2IntMaps.emptyMap() + return activeConfig?.blockStates() ?: Reference2IntMaps.emptyMap() + } + fun blockEntityRemoved(blockEntity: BlockEntity) { activeConfig?.blockEntityRemoved(blockEntity) } @@ -680,11 +794,11 @@ class Multiblock( fun update(levelAccessor: LevelAccessor): Boolean { val activeConfig = activeConfig - if (activeConfig != null && activeConfig.update(levelAccessor)) { + if (activeConfig != null && activeConfig.update(levelAccessor) && customChecks.all { it.test(this) }) { return true } else if (activeConfig != null) { for (config in configurations) { - if (config !== activeConfig && config.update(levelAccessor)) { + if (config !== activeConfig && config.update(levelAccessor) && customChecks.all { it.test(this) }) { this.activeConfig = config return true } @@ -695,7 +809,7 @@ class Multiblock( return false } else { for (config in configurations) { - if (config.update(levelAccessor)) { + if (config.update(levelAccessor) && customChecks.all { it.test(this) }) { this.activeConfig = config this.isValid = true return true @@ -720,7 +834,7 @@ class Multiblock( else -> throw IllegalArgumentException(direction.name) } - isValid = config.update(levelAccessor) + isValid = config.update(levelAccessor) && customChecks.all { it.test(this) } if (isValid) activeConfig = config From 3ddb4d3d83b9d4c9918778cf3edaf5fea39c8bbb Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Tue, 30 Jan 2024 17:45:28 +0700 Subject: [PATCH 17/38] EnergyContainerInputSlot --- src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt | 7 +++++++ 1 file changed, 7 insertions(+) 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 be03785a9..69b2b53d1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt @@ -7,6 +7,7 @@ import net.minecraft.world.entity.player.Player 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.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy @@ -129,6 +130,12 @@ open class ChargeSlot(container: Container, index: Int, x: Int = 0, y: Int = 0) } } +open class EnergyContainerInputSlot(container: Container, index: Int, x: Int = 0, y: Int = 0, val direction: FlowDirection = FlowDirection.BI_DIRECTIONAL) : MatterySlot(container, index, x, y) { + override fun mayPlace(itemStack: ItemStack): Boolean { + return super.mayPlace(itemStack) && itemStack.getCapability(ForgeCapabilities.ENERGY).map { direction.test(FlowDirection.of(it.canReceive(), it.canExtract())) }.orElse(false) + } +} + open class MatterContainerInputSlot( container: Container, index: Int, From 059270a2ec3c09f250417dc9dab0491366177069 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 15 Feb 2024 18:47:06 +0700 Subject: [PATCH 18/38] Add lots of multiblock related stuff, more blackhole generator multiblock testcode --- .../mc/otm/datagen/lang/English.kt | 9 + .../mc/otm/datagen/lang/Russian.kt | 10 + .../mc/otm/datagen/loot/LootTablesData.kt | 4 + .../dbotthepony/mc/otm/datagen/tags/Tags.kt | 4 + .../tech/BlackHoleGeneratorBlockEntity.kt | 239 ++++++++++++++++++ .../entity/tech/EnergyHatchBlockEntity.kt | 87 +++++++ .../block/entity/tech/ItemHatchBlockEntity.kt | 50 ++++ .../entity/tech/MatterHatchBlockEntity.kt | 89 +++++++ .../otm/block/tech/BlackHoleGeneratorBlock.kt | 56 ++++ .../mc/otm/block/tech/HatchBlock.kt | 37 +++ .../ru/dbotthepony/mc/otm/capability/Ext.kt | 25 ++ .../client/screen/tech/EnergyHatchScreen.kt | 48 ++++ .../otm/client/screen/tech/ItemHatchScreen.kt | 32 +++ .../client/screen/tech/MatterHatchScreen.kt | 43 ++++ .../mc/otm/config/MachinesConfig.kt | 34 ++- .../kotlin/ru/dbotthepony/mc/otm/core/Ext.kt | 6 + .../ru/dbotthepony/mc/otm/core/Multiblock.kt | 4 +- .../mc/otm/core/util/FriendlyStreams.kt | 12 +- .../mc/otm/menu/tech/EnergyHatchMenu.kt | 52 ++++ .../mc/otm/menu/tech/ItemHatchMenu.kt | 52 ++++ .../mc/otm/menu/tech/MatterHatchMenu.kt | 49 ++++ .../mc/otm/registry/MBlockEntities.kt | 19 +- .../ru/dbotthepony/mc/otm/registry/MBlocks.kt | 25 +- .../ru/dbotthepony/mc/otm/registry/MItems.kt | 16 ++ .../ru/dbotthepony/mc/otm/registry/MMenus.kt | 18 ++ .../ru/dbotthepony/mc/otm/registry/MNames.kt | 11 + 26 files changed, 1007 insertions(+), 24 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BlackHoleGeneratorBlockEntity.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyHatchBlockEntity.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ItemHatchBlockEntity.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/MatterHatchBlockEntity.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BlackHoleGeneratorBlock.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/HatchBlock.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyHatchScreen.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ItemHatchScreen.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/MatterHatchScreen.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyHatchMenu.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ItemHatchMenu.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/MatterHatchMenu.kt diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt index 2140cb5ed..6cecd4098 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt @@ -479,6 +479,14 @@ private fun blocks(provider: MatteryLanguageProvider) { addBlock(MBlocks.DRIVE_VIEWER.values, "Drive Viewer") add(MBlocks.BLACK_HOLE, "Local Anomalous Spacetime Dilation Singular Point") + add(MBlocks.BLACK_HOLE_GENERATOR, "Matter Acceleration Power Generator") + + add(MBlocks.ENERGY_INPUT_HATCH, "Energy Input Hatch") + add(MBlocks.ITEM_INPUT_HATCH, "Item Input Hatch") + add(MBlocks.MATTER_INPUT_HATCH, "Matter Input Hatch") + add(MBlocks.ENERGY_OUTPUT_HATCH, "Energy Output Hatch") + add(MBlocks.ITEM_OUTPUT_HATCH, "Item Output Hatch") + add(MBlocks.MATTER_OUTPUT_HATCH, "Matter Output Hatch") addBlock(MBlocks.COBBLESTONE_GENERATOR.values, "Cobblestone Generator") add(MBlocks.INFINITE_WATER_SOURCE, "Infinite Water Source") @@ -810,6 +818,7 @@ private fun androidFeatures(provider: MatteryLanguageProvider) { private fun gui(provider: MatteryLanguageProvider) { with(provider.english) { + gui("part_of_multiblock", "Part of multiblock structure, useless on its own") gui("quicksearch", "Quick search...") gui("painter.is_bulk", "Bulk painting") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt index b975b1b16..14b5a1c73 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt @@ -484,7 +484,16 @@ private fun blocks(provider: MatteryLanguageProvider) { addBlock(MBlocks.COBBLESTONE_GENERATOR.values, "Генератор булыжника") add(MBlocks.INFINITE_WATER_SOURCE, "Неиссякаемый источник воды") add(MBlocks.INFINITE_WATER_SOURCE, "desc", "Выталкивает воду в соседние блоки автоматически") + add(MBlocks.BLACK_HOLE, "Локализированная сингулярная точка аномального искажения пространства-времени") + add(MBlocks.BLACK_HOLE_GENERATOR, "Генератор энергии ускорением материи") + + add(MBlocks.ENERGY_INPUT_HATCH, "Входной энергетический клапан") + add(MBlocks.ITEM_INPUT_HATCH, "Входной предметный клапан") + add(MBlocks.MATTER_INPUT_HATCH, "Входной клапан материи") + add(MBlocks.ENERGY_OUTPUT_HATCH, "Выходной энергетический клапан") + add(MBlocks.ITEM_OUTPUT_HATCH, "Выходной предметный клапан") + add(MBlocks.MATTER_OUTPUT_HATCH, "Выходной клапан материи") add(MBlocks.DEV_CHEST, "Сундук разработчика") add(MBlocks.DEV_CHEST, "desc", "Хранит все предметы, которые есть в игре") @@ -814,6 +823,7 @@ private fun androidFeatures(provider: MatteryLanguageProvider) { private fun gui(provider: MatteryLanguageProvider) { with(provider.russian) { + gui("part_of_multiblock", "Часть мультиблока, бесполезен сам по себе") gui("quicksearch", "Быстрый поиск...") gui("painter.is_bulk", "Массовая покраска") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt index 3c8e2b49b..279e8de01 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootTablesData.kt @@ -169,4 +169,8 @@ fun addLootTables(lootTables: LootTables) { lootTables.tile(MBlocks.PATTERN_STORAGE) lootTables.tile(MBlocks.MATTER_CAPACITOR_BANK.values) lootTables.tile(MBlocks.MATTER_BOTTLER.values) + + lootTables.tile(MBlocks.BLACK_HOLE_GENERATOR) + lootTables.tile(MBlocks.ITEM_INPUT_HATCH) + lootTables.tile(MBlocks.ITEM_OUTPUT_HATCH) } diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt index 8aa8bcef3..7bb46aece 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt @@ -229,6 +229,10 @@ fun addTags(tagsProvider: TagsProvider) { *MBlocks.MATTER_RECONSTRUCTOR.values.toTypedArray(), MBlocks.FLUID_TANK, *MBlocks.ANDROID_CHARGER.values.toTypedArray(), + + MBlocks.BLACK_HOLE_GENERATOR, + MBlocks.ITEM_INPUT_HATCH, + MBlocks.ITEM_OUTPUT_HATCH, ), Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_ANVIL, Tiers.IRON) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BlackHoleGeneratorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BlackHoleGeneratorBlockEntity.kt new file mode 100644 index 000000000..2c1448264 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BlackHoleGeneratorBlockEntity.kt @@ -0,0 +1,239 @@ +package ru.dbotthepony.mc.otm.block.entity.tech + +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import it.unimi.dsi.fastutil.objects.ObjectArraySet +import net.minecraft.core.BlockPos +import net.minecraft.core.SectionPos +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.block.state.BlockState +import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity +import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity +import ru.dbotthepony.mc.otm.config.MachinesConfig +import ru.dbotthepony.mc.otm.core.Multiblock +import ru.dbotthepony.mc.otm.core.MultiblockBuilder +import ru.dbotthepony.mc.otm.core.getBlockStateNow +import ru.dbotthepony.mc.otm.core.immutableList +import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.mc.otm.core.math.plus +import ru.dbotthepony.mc.otm.core.math.times +import ru.dbotthepony.mc.otm.core.multiblockConfiguration +import ru.dbotthepony.mc.otm.registry.MBlockEntities +import ru.dbotthepony.mc.otm.registry.MBlocks + +class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.BLACK_HOLE_GENERATOR, blockPos, blockState) { + private var multiblock: Multiblock? = null + private var lastRange = -1 + + private fun findBlackHoleRange(): Int { + val normal = blockRotation.normal + val level = level!! + + if (lastRange != -1) { + val pos = blockPos + normal * lastRange + + if (level.getBlockStateNow(pos).block == MBlocks.BLACK_HOLE) { + return lastRange + } + } + + for (i in 5 until 64) { + val pos = blockPos + normal * i + + if (level.getBlockStateNow(pos).block == MBlocks.BLACK_HOLE) { + return i + } + } + + return -1 + } + + override fun tick() { + super.tick() + + val level = level!! + + if (lastRange == -1) { + val found = findBlackHoleRange() + + if (found != -1) { + lastRange = found + multiblock = CONFIGURATIONS[found - 5].value.create(blockPos) + } else { + multiblock = null + } + } + + val multiblock = multiblock + + if (multiblock != null) { + if (!multiblock.update(level, blockRotation.front)) { + val found = findBlackHoleRange() + + if (found == -1) { + this.multiblock = null + } else if (found != lastRange) { + lastRange = found + this.multiblock = CONFIGURATIONS[found - 5].value.create(blockPos) + } + } else { + val blackHole = multiblock.blockEntities(BLACK_HOLE).first() + val matterHatches = multiblock.blockEntities(MatterHatchBlockEntity.INPUT_TAG) + val energyHatches = multiblock.blockEntities(EnergyHatchBlockEntity.OUTPUT_TAG) + + if (matterHatches.isEmpty() || energyHatches.isEmpty()) return + + var required = MachinesConfig.BlackHoleGenerator.MATTER_RATE + + for (hatch in matterHatches) { + required -= hatch.matter.extractMatter(required, true) + if (required <= Decimal.ZERO) break + } + + if (required > Decimal.ZERO) return + + var energyLeftover = blackHole.mass / MachinesConfig.BlackHoleGenerator.MASS_DIVISOR + + for (hatch in energyHatches) { + energyLeftover -= hatch.energy.receiveEnergy(energyLeftover, true) + if (energyLeftover <= Decimal.ZERO) break + } + + if (energyLeftover > Decimal.ZERO) return + + required = MachinesConfig.BlackHoleGenerator.MATTER_RATE + + for (hatch in matterHatches) { + required -= hatch.matter.extractMatter(required, false) + if (required <= Decimal.ZERO) break + } + + energyLeftover = blackHole.mass / MachinesConfig.BlackHoleGenerator.MASS_DIVISOR + + for (hatch in energyHatches) { + energyLeftover -= hatch.energy.receiveEnergy(energyLeftover, false) + if (energyLeftover <= Decimal.ZERO) break + } + + blackHole.mass += MachinesConfig.BlackHoleGenerator.MASS_FEEDING_RATIO * MachinesConfig.BlackHoleGenerator.MATTER_RATE + } + } + } + + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? { + return null + } + + companion object { + val BLACK_HOLE = MultiblockBuilder.EntityTag(BlackHoleBlockEntity::class) + + private fun points(x: Int, z: Int, result: ObjectArraySet) { + if (x == 0) { + result.add(BlockPos(0, 0, z)) + result.add(BlockPos(0, 0, -z)) + result.add(BlockPos(z, 0, 0)) + result.add(BlockPos(-z, 0, 0)) + } else if (x == z) { + result.add(BlockPos(x, 0, z)) + result.add(BlockPos(-x, 0, z)) + result.add(BlockPos(x, 0, -z)) + result.add(BlockPos(-x, 0, -z)) + } else if (x < z) { + result.add(BlockPos(x, 0, z)) + result.add(BlockPos(-x, 0, z)) + result.add(BlockPos(x, 0, -z)) + result.add(BlockPos(-x, 0, -z)) + + result.add(BlockPos(z, 0, x)) + result.add(BlockPos(-z, 0, x)) + result.add(BlockPos(z, 0, -x)) + result.add(BlockPos(-z, 0, -x)) + } + } + + private fun ring(size: Int): ObjectArrayList { + val positions = ObjectArraySet() + var x = 0 + var y = size + var p = (5 - size * 4) / 4 + points(x, y, positions) + + while (x < y) { + x++ + + if (p < 0) { + p += x * 2 + 1 + } else { + y-- + p += (x - y) * 2 + 1 + } + + points(x, y, positions) + } + + val result = ObjectArrayList(positions.size) + + for (pos in positions) { + if (pos.x == 0 && pos.z + size == 0) continue + result.add(BlockPos(pos.x, 0, pos.z + size)) + } + + return result + } + + val CONFIGURATIONS = immutableList { + for (i2 in 0 until 59) { + val i = i2 + 5 + + accept(lazy { + multiblockConfiguration { + builder.customCheck { + val blocks = it.blocks() + + blocks.getInt(MBlocks.MATTER_INJECTOR) == 1 && + blocks.getInt(MBlocks.ANTIMATTER_INJECTOR) == 1 && + blocks.getInt(MBlocks.HIGH_ENERGY_PARTICLE_COLLECTOR) == 1 + } + + block(MBlocks.BLACK_HOLE_GENERATOR) + + relative(BlockPos(0, 0, i)) { + block(MBlocks.BLACK_HOLE) + tag(BLACK_HOLE) + } + + val ring = ring(i) + + for (pos in ring) { + val node = relative(pos) + + if ((pos.x == i || pos.x == -i) && pos.z == i) { + node.block(MBlocks.MATTER_INJECTOR) + node.block(MBlocks.ANTIMATTER_INJECTOR) + node.tagBlock() + } else if (pos.x == 0 && pos.z == i * 2) { + node.block(MBlocks.HIGH_ENERGY_PARTICLE_COLLECTOR) + node.tagBlock() + } else if (pos.x == i || pos.x == -i || pos.z == i * 2 || pos.z == 0) { + node.or { + block(MBlocks.ENERGY_OUTPUT_HATCH) + tag(EnergyHatchBlockEntity.OUTPUT_TAG) + } + + node.or { + block(MBlocks.MATTER_INPUT_HATCH) + tag(MatterHatchBlockEntity.INPUT_TAG) + } + + node.block(MBlocks.MULTIBLOCK_STRUCTURE) + } else { + node.block(MBlocks.MULTIBLOCK_STRUCTURE) + } + } + } + }) + } + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyHatchBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyHatchBlockEntity.kt new file mode 100644 index 000000000..af76a7e9d --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyHatchBlockEntity.kt @@ -0,0 +1,87 @@ +package ru.dbotthepony.mc.otm.block.entity.tech + +import net.minecraft.core.BlockPos +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.AbstractContainerMenu +import net.minecraft.world.item.ItemStack +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.mc.otm.block.entity.MatteryDeviceBlockEntity +import ru.dbotthepony.mc.otm.capability.FlowDirection +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl +import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage +import ru.dbotthepony.mc.otm.capability.moveEnergy +import ru.dbotthepony.mc.otm.config.EnergyBalanceValues +import ru.dbotthepony.mc.otm.config.MachinesConfig +import ru.dbotthepony.mc.otm.container.HandlerFilter +import ru.dbotthepony.mc.otm.container.MatteryContainer +import ru.dbotthepony.mc.otm.core.MultiblockBuilder +import ru.dbotthepony.mc.otm.core.ifPresentK +import ru.dbotthepony.mc.otm.menu.tech.EnergyHatchMenu +import ru.dbotthepony.mc.otm.registry.MBlockEntities + +class EnergyHatchBlockEntity( + val isInput: Boolean, + capacity: EnergyBalanceValues, + type: BlockEntityType<*>, + blockPos: BlockPos, + blockState: BlockState +) : MatteryDeviceBlockEntity(type, blockPos, blockState) { + val energy = ProfiledEnergyStorage(BlockEnergyStorageImpl(this::markDirtyFast, FlowDirection.input(isInput), capacity)) + + val container = object : MatteryContainer(this::markDirtyFast, CAPACITY) { + override fun getMaxStackSize(slot: Int, itemStack: ItemStack): Int { + return 1 + } + }.also(::addDroppableContainer) + + val itemHandler = container.handler(if (isInput) HandlerFilter.Dischargeable else HandlerFilter.Chargeable) + + init { + savetables.stateful(::energy, ENERGY_KEY) + savetables.stateful(::container, BATTERY_KEY) + + // it would cause a lot of frustration if hatches accept stuff only though one face + exposeGlobally(ForgeCapabilities.ENERGY, energy) + exposeGlobally(MatteryCapability.ENERGY, energy) + exposeGlobally(ForgeCapabilities.ITEM_HANDLER, itemHandler) + } + + override fun tick() { + super.tick() + + if (!redstoneControl.isBlockedByRedstone) { + container.forEach { + it.getCapability(ForgeCapabilities.ENERGY).ifPresentK { + if (isInput) { + moveEnergy(it, energy, simulate = false) + } else { + moveEnergy(energy, it, simulate = false) + } + } + } + } + } + + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { + return EnergyHatchMenu(isInput, containerID, inventory, this) + } + + companion object { + const val CAPACITY = 1 + + val INPUT_TAG = MultiblockBuilder.EntityTag(EnergyHatchBlockEntity::class) { it.isInput } + val OUTPUT_TAG = MultiblockBuilder.EntityTag(EnergyHatchBlockEntity::class) { !it.isInput } + + fun input(blockPos: BlockPos, blockState: BlockState): EnergyHatchBlockEntity { + return EnergyHatchBlockEntity(true, MachinesConfig.ENERGY_HATCH, MBlockEntities.ENERGY_INPUT_HATCH, blockPos, blockState) + } + + fun output(blockPos: BlockPos, blockState: BlockState): EnergyHatchBlockEntity { + return EnergyHatchBlockEntity(false, MachinesConfig.ENERGY_HATCH, MBlockEntities.ENERGY_OUTPUT_HATCH, blockPos, blockState) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ItemHatchBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ItemHatchBlockEntity.kt new file mode 100644 index 000000000..2e00b1113 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ItemHatchBlockEntity.kt @@ -0,0 +1,50 @@ +package ru.dbotthepony.mc.otm.block.entity.tech + +import net.minecraft.core.BlockPos +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.block.entity.BlockEntityType +import net.minecraft.world.level.block.state.BlockState +import net.minecraftforge.common.capabilities.ForgeCapabilities +import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity +import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity +import ru.dbotthepony.mc.otm.container.HandlerFilter +import ru.dbotthepony.mc.otm.container.MatteryContainer +import ru.dbotthepony.mc.otm.core.MultiblockBuilder +import ru.dbotthepony.mc.otm.menu.tech.ItemHatchMenu +import ru.dbotthepony.mc.otm.registry.MBlockEntities + +class ItemHatchBlockEntity( + val isInput: Boolean, + type: BlockEntityType<*>, + blockPos: BlockPos, + blockState: BlockState +) : MatteryDeviceBlockEntity(type, blockPos, blockState) { + val container = MatteryContainer(this::markDirtyFast, CAPACITY).also(::addDroppableContainer) + val itemHandler = container.handler(if (isInput) HandlerFilter.OnlyIn else HandlerFilter.OnlyOut) + + init { + savetables.stateful(::container, INVENTORY_KEY) + exposeGlobally(ForgeCapabilities.ITEM_HANDLER, itemHandler) + } + + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { + return ItemHatchMenu(isInput, containerID, inventory, this) + } + + companion object { + const val CAPACITY = CargoCrateBlockEntity.CAPACITY + + val INPUT_TAG = MultiblockBuilder.EntityTag(ItemHatchBlockEntity::class) { it.isInput } + val OUTPUT_TAG = MultiblockBuilder.EntityTag(ItemHatchBlockEntity::class) { !it.isInput } + + fun input(blockPos: BlockPos, blockState: BlockState): ItemHatchBlockEntity { + return ItemHatchBlockEntity(true, MBlockEntities.ITEM_INPUT_HATCH, blockPos, blockState) + } + + fun output(blockPos: BlockPos, blockState: BlockState): ItemHatchBlockEntity { + return ItemHatchBlockEntity(false, MBlockEntities.ITEM_OUTPUT_HATCH, blockPos, blockState) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/MatterHatchBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/MatterHatchBlockEntity.kt new file mode 100644 index 000000000..5e0f7b7a0 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/MatterHatchBlockEntity.kt @@ -0,0 +1,89 @@ +package ru.dbotthepony.mc.otm.block.entity.tech + +import net.minecraft.core.BlockPos +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.AbstractContainerMenu +import net.minecraft.world.item.ItemStack +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.mc.otm.block.entity.MatteryDeviceBlockEntity +import ru.dbotthepony.mc.otm.capability.FlowDirection +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl +import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage +import ru.dbotthepony.mc.otm.capability.moveMatter +import ru.dbotthepony.mc.otm.config.MachinesConfig +import ru.dbotthepony.mc.otm.container.HandlerFilter +import ru.dbotthepony.mc.otm.container.MatteryContainer +import ru.dbotthepony.mc.otm.core.MultiblockBuilder +import ru.dbotthepony.mc.otm.core.ifPresentK +import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.mc.otm.menu.tech.MatterHatchMenu +import ru.dbotthepony.mc.otm.registry.MBlockEntities + +class MatterHatchBlockEntity( + val isInput: Boolean, + type: BlockEntityType<*>, + blockPos: BlockPos, + blockState: BlockState +) : MatteryDeviceBlockEntity(type, blockPos, blockState) { + val container = object : MatteryContainer(this::markDirtyFast, CAPACITY) { + override fun getMaxStackSize(slot: Int, itemStack: ItemStack): Int { + return 1 + } + }.also(::addDroppableContainer) + + val matter = ProfiledMatterStorage(MatterStorageImpl(this::markDirtyFast, FlowDirection.input(isInput), MachinesConfig::MATTER_HATCH)) + + val itemHandler = if (isInput) { + container.handler(HandlerFilter.MatterProviders) + } else { + container.handler(HandlerFilter.MatterConsumers) + } + + init { + savetables.stateful(::container, INVENTORY_KEY) + savetables.stateful(::matter, MATTER_STORAGE_KEY) + + // it would cause a lot of frustration if hatches accept stuff only though one face + exposeGlobally(ForgeCapabilities.ITEM_HANDLER, itemHandler) + exposeGlobally(MatteryCapability.MATTER, matter) + } + + override fun tick() { + super.tick() + + if (!redstoneControl.isBlockedByRedstone && matter.missingMatter > Decimal.ZERO) { + container.forEach { + it.getCapability(MatteryCapability.MATTER).ifPresentK { + if (isInput) { + moveMatter(it, matter, simulate = false) + } else { + moveMatter(matter, it, simulate = false) + } + } + } + } + } + + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { + return MatterHatchMenu(isInput, containerID, inventory, this) + } + + companion object { + const val CAPACITY = 1 + + val INPUT_TAG = MultiblockBuilder.EntityTag(MatterHatchBlockEntity::class) { it.isInput } + val OUTPUT_TAG = MultiblockBuilder.EntityTag(MatterHatchBlockEntity::class) { !it.isInput } + + fun input(blockPos: BlockPos, blockState: BlockState): MatterHatchBlockEntity { + return MatterHatchBlockEntity(true, MBlockEntities.ITEM_INPUT_HATCH, blockPos, blockState) + } + + fun output(blockPos: BlockPos, blockState: BlockState): MatterHatchBlockEntity { + return MatterHatchBlockEntity(false, MBlockEntities.ITEM_OUTPUT_HATCH, blockPos, blockState) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BlackHoleGeneratorBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BlackHoleGeneratorBlock.kt new file mode 100644 index 000000000..fc722dfe9 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BlackHoleGeneratorBlock.kt @@ -0,0 +1,56 @@ +package ru.dbotthepony.mc.otm.block.tech + +import net.minecraft.core.BlockPos +import net.minecraft.core.SectionPos +import net.minecraft.world.item.context.BlockPlaceContext +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.EntityBlock +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.entity.BlockEntityTicker +import net.minecraft.world.level.block.entity.BlockEntityType +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.material.MapColor +import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock +import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity +import ru.dbotthepony.mc.otm.block.entity.tech.BlackHoleGeneratorBlockEntity +import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom +import ru.dbotthepony.mc.otm.core.math.plus +import ru.dbotthepony.mc.otm.core.math.times + +class BlackHoleGeneratorBlock : RotatableMatteryBlock(Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)), EntityBlock { + override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity { + return BlackHoleGeneratorBlockEntity(blockPos, blockState) + } + + override fun getTicker(level: Level, blockState: BlockState, blockEntityType: BlockEntityType): BlockEntityTicker? { + if (level.isClientSide) + return null + + return BlockEntityTicker { _, _, _, tile -> if (tile is BlackHoleGeneratorBlockEntity) tile.tick() } + } + + override fun getStateForPlacement(context: BlockPlaceContext): BlockState? { + var state = super.getStateForPlacement(context) ?: return null + val blockPos = context.clickedPos + val level = context.level + + for (face in BlockRotationFreedom.HORIZONTAL.possibleValues) { + val dir = face.normal + + for (i in 4 ..64) { + val pos = blockPos + dir * i + val chunk = level.chunkSource.getChunkNow(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z)) ?: continue + val getState = chunk.getBlockState(pos) + + if (!getState.isAir) { + if (chunk.getBlockEntity(pos) is BlackHoleBlockEntity) { + state = state.setValue(BlockRotationFreedom.HORIZONTAL.property, face) + break + } + } + } + } + + return state + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/HatchBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/HatchBlock.kt new file mode 100644 index 000000000..6a9871af4 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/HatchBlock.kt @@ -0,0 +1,37 @@ +package ru.dbotthepony.mc.otm.block.tech + +import net.minecraft.ChatFormatting +import net.minecraft.core.BlockPos +import net.minecraft.world.item.context.BlockPlaceContext +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.EntityBlock +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.entity.BlockEntityTicker +import net.minecraft.world.level.block.entity.BlockEntityType +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.material.MapColor +import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock +import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity +import ru.dbotthepony.mc.otm.core.TranslatableComponent + +class HatchBlock(val factory: BlockEntityType.BlockEntitySupplier, val needsTicking: Boolean = false) : RotatableMatteryBlock(Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(80.0f)), EntityBlock { + override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity { + return factory.create(blockPos, blockState) + } + + override fun getTicker(level: Level, blockState: BlockState, type: BlockEntityType): BlockEntityTicker? { + if (needsTicking && !level.isClientSide) { + return BlockEntityTicker { _, _, _, tile -> if (tile is MatteryBlockEntity) tile.tick() } + } + + return null + } + + override fun faceToPlayer(context: BlockPlaceContext): Boolean { + return true + } + + init { + tooltips.add(TranslatableComponent("otm.gui.part_of_multiblock").withStyle(ChatFormatting.GRAY)) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt index ecc314620..bc93e7e4a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt @@ -15,6 +15,7 @@ import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.fluid.iterator import ru.dbotthepony.mc.otm.capability.fluid.stream +import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage import ru.dbotthepony.mc.otm.client.ShiftPressedCond import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorAwareStream import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorStream @@ -289,6 +290,30 @@ fun moveEnergy(source: IEnergyStorage, destination: IEnergyStorage, amount: Deci return Decimal.ZERO } +@Suppress("name_shadowing") +fun moveMatter(source: IMatterStorage, destination: IMatterStorage, amount: Decimal = Decimal.LONG_MAX_VALUE.coerceAtLeast(source.storedMatter), simulate: Boolean, ignoreFlowRestrictions: Boolean = false): Decimal { + val extracted = if (ignoreFlowRestrictions) source.extractMatter(amount, true) else source.extractMatterChecked(amount, true) + + if (extracted.isPositive) { + val received = destination.receiveMatterChecked(extracted, true) + + if (received.isPositive) { + val extracted = if (ignoreFlowRestrictions) source.extractMatter(received, true) else source.extractMatterChecked(received, true) + + if (extracted.isPositive) { + if (simulate) { + return extracted + } + + val extracted = if (ignoreFlowRestrictions) source.extractMatter(received, false) else source.extractMatterChecked(received, false) + return destination.receiveMatterChecked(extracted, false) + } + } + } + + return Decimal.ZERO +} + internal fun IFluidHandler.fluidLevel(tooltips: (Component) -> Unit) { val fluid = getFluidInTank(0) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyHatchScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyHatchScreen.kt new file mode 100644 index 000000000..18cdb016e --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyHatchScreen.kt @@ -0,0 +1,48 @@ +package ru.dbotthepony.mc.otm.client.screen.tech + +import net.minecraft.network.chat.Component +import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.mc.otm.client.render.UVWindingOrder +import ru.dbotthepony.mc.otm.client.screen.MatteryScreen +import ru.dbotthepony.mc.otm.client.screen.panels.Dock +import ru.dbotthepony.mc.otm.client.screen.panels.DockResizeMode +import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel +import ru.dbotthepony.mc.otm.client.screen.panels.SpritePanel +import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls +import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel +import ru.dbotthepony.mc.otm.client.screen.panels.slot.MatterCapacitorSlotPanel +import ru.dbotthepony.mc.otm.client.screen.widget.HorizontalProfiledPowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel +import ru.dbotthepony.mc.otm.menu.tech.EnergyHatchMenu +import ru.dbotthepony.mc.otm.menu.tech.MatterHatchMenu + +class EnergyHatchScreen(menu: EnergyHatchMenu, inventory: Inventory, title: Component) : MatteryScreen(menu, inventory, title) { + override fun makeMainFrame(): FramePanel> { + val frame = FramePanel(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH, AbstractSlotPanel.SIZE, getTitle()) + + frame.makeCloseButton() + frame.onClose { onClose() } + + for (slot in menu.inputSlots) { + val panel = MatterCapacitorSlotPanel(this, frame, slot) + panel.dock = Dock.LEFT + panel.dockResize = DockResizeMode.NONE + } + + val arrow = SpritePanel(this, frame, ProgressGaugePanel.GAUGE_BACKGROUND) + arrow.dockLeft = 2f + arrow.dockRight = 2f + arrow.dock = Dock.LEFT + arrow.dockResize = DockResizeMode.NONE + + if (!menu.isInput) + arrow.winding = UVWindingOrder.FLOP + + val gauge = HorizontalProfiledPowerGaugePanel(this, frame, menu.gauge) + gauge.dock = Dock.RIGHT + + DeviceControls(this, frame, redstoneConfig = menu.redstone) + + return frame + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ItemHatchScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ItemHatchScreen.kt new file mode 100644 index 000000000..7408515ea --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ItemHatchScreen.kt @@ -0,0 +1,32 @@ +package ru.dbotthepony.mc.otm.client.screen.tech + +import net.minecraft.network.chat.Component +import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.mc.otm.client.screen.MatteryScreen +import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel +import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls +import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel +import ru.dbotthepony.mc.otm.client.screen.panels.slot.UserFilteredSlotPanel +import ru.dbotthepony.mc.otm.menu.tech.ItemHatchMenu + +class ItemHatchScreen(menu: ItemHatchMenu, inventory: Inventory, title: Component) : MatteryScreen(menu, inventory, title) { + override fun makeMainFrame(): FramePanel> { + val frame = FramePanel(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH, 22f + 4f + 6f * 18f, getTitle()) + + frame.makeCloseButton() + frame.onClose { onClose() } + frame.makeHelpButton().addSlotFiltersHelp() + + val grid = GridPanel(this, frame, 8f, 18f, 9f * 18f, 6f * 18f, 9, 6) + + for (slot in menu.storageSlots) + UserFilteredSlotPanel.of(this, grid, slot) + + if (menu.isInput) { + val controls = DeviceControls(this, frame) + controls.sortingButtons(menu.sort) + } + + return frame + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/MatterHatchScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/MatterHatchScreen.kt new file mode 100644 index 000000000..bb0287fe9 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/MatterHatchScreen.kt @@ -0,0 +1,43 @@ +package ru.dbotthepony.mc.otm.client.screen.tech + +import net.minecraft.network.chat.Component +import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.mc.otm.client.render.UVWindingOrder +import ru.dbotthepony.mc.otm.client.screen.MatteryScreen +import ru.dbotthepony.mc.otm.client.screen.panels.Dock +import ru.dbotthepony.mc.otm.client.screen.panels.DockResizeMode +import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel +import ru.dbotthepony.mc.otm.client.screen.panels.SpritePanel +import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls +import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel +import ru.dbotthepony.mc.otm.client.screen.panels.slot.MatterCapacitorSlotPanel +import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel +import ru.dbotthepony.mc.otm.menu.tech.MatterHatchMenu + +class MatterHatchScreen(menu: MatterHatchMenu, inventory: Inventory, title: Component) : MatteryScreen(menu, inventory, title) { + override fun makeMainFrame(): FramePanel> { + val frame = FramePanel(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH, AbstractSlotPanel.SIZE, getTitle()) + + frame.makeCloseButton() + frame.onClose { onClose() } + + for (slot in menu.inputSlots) { + val panel = MatterCapacitorSlotPanel(this, frame, slot) + panel.dock = Dock.LEFT + panel.dockResize = DockResizeMode.NONE + } + + val arrow = SpritePanel(this, frame, ProgressGaugePanel.GAUGE_BACKGROUND) + arrow.dockLeft = 2f + arrow.dockRight = 2f + arrow.dock = Dock.LEFT + arrow.dockResize = DockResizeMode.NONE + + if (!menu.isInput) + arrow.winding = UVWindingOrder.FLOP + + DeviceControls(this, frame, redstoneConfig = menu.redstone) + + return frame + } +} 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 5eff8cfc2..4f08725d3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/MachinesConfig.kt @@ -1,6 +1,5 @@ package ru.dbotthepony.mc.otm.config -import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.defineDecimal import ru.dbotthepony.mc.otm.registry.MNames @@ -193,6 +192,39 @@ object MachinesConfig : AbstractConfig("machines") { maxExperience = 200.0 ) + val ENERGY_HATCH = conciseValues( + "ENERGY_HATCH", + storage = Decimal(6_000_000), + throughput = Decimal(200_000) + ) + + val MATTER_HATCH by builder + .comment("Internal buffer of matter hatch") + .defineDecimal("MATTER_HATCH", Decimal(200), Decimal.ONE) + + object BlackHoleGenerator { + init { + builder.push("BLACK_HOLE_GENERATOR") + } + + val MATTER_RATE: Decimal + get() = Decimal("0.25") + + val MASS_DIVISOR: Decimal + get() = Decimal.TEN + + val MASS_FEEDING_RATIO: Decimal + get() = Decimal("0.1") + + init { + builder.pop() + } + } + + init { + BlackHoleGenerator + } + object Upgrades { init { builder.push("UPGRADES") 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 deb2df51e..f5ee5effd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt @@ -13,6 +13,7 @@ import com.google.gson.JsonPrimitive import it.unimi.dsi.fastutil.objects.ObjectComparators import net.minecraft.Util import net.minecraft.core.BlockPos +import net.minecraft.core.SectionPos import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtAccounter import net.minecraft.network.FriendlyByteBuf @@ -26,6 +27,7 @@ import net.minecraft.world.item.Items import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.level.BlockGetter import net.minecraft.world.level.Level +import net.minecraft.world.level.LevelAccessor import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Blocks import net.minecraft.world.level.block.state.BlockState @@ -104,6 +106,10 @@ operator fun JsonObject.set(s: String, value: String) = add(s, JsonPrimitive(val operator fun JsonObject.set(s: String, value: Number) = add(s, JsonPrimitive(value)) operator fun JsonObject.set(s: String, value: Boolean) = add(s, JsonPrimitive(value)) +fun LevelAccessor.getBlockStateNow(pos: BlockPos): BlockState { + return chunkSource.getChunkNow(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z))?.getBlockState(pos) ?: Blocks.AIR.defaultBlockState() +} + fun LazyOptional.orNull(): T? { if (!isPresent) { return null diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt index 783722ae3..5ec05fd65 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Multiblock.kt @@ -189,7 +189,7 @@ class MultiblockBuilder { fun block(block: Block): T { predicates.add { pos, access -> // use getChunk directly because we don't want to chunkload - (access.getChunk(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z), ChunkStatus.FULL, false)?.getBlockState(pos) ?: Blocks.AIR.defaultBlockState()).`is`(block) + access.getBlockStateNow(pos).block == block } return this as T @@ -198,7 +198,7 @@ class MultiblockBuilder { fun block(block: TagKey): T { predicates.add { pos, access -> // use getChunk directly because we don't want to chunkload - (access.getChunk(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z), ChunkStatus.FULL, false)?.getBlockState(pos) ?: Blocks.AIR.defaultBlockState()).`is`(block) + access.getBlockStateNow(pos).`is`(block) } return this as T diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/FriendlyStreams.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/FriendlyStreams.kt index 38c7b6e0a..2327a2abf 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/FriendlyStreams.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/FriendlyStreams.kt @@ -198,12 +198,12 @@ fun InputStream.readLong(): Long { } return (read().toLong() shl 48) or - (read().toLong() shl 40) or - (read().toLong() shl 32) or - (read().toLong() shl 24) or - (read().toLong() shl 16) or - (read().toLong() shl 8) or - read().toLong() + (read().toLong() shl 40) or + (read().toLong() shl 32) or + (read().toLong() shl 24) or + (read().toLong() shl 16) or + (read().toLong() shl 8) or + read().toLong() } fun OutputStream.writeFloat(value: Float) = writeInt(value.toBits()) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyHatchMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyHatchMenu.kt new file mode 100644 index 000000000..521800310 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/EnergyHatchMenu.kt @@ -0,0 +1,52 @@ +package ru.dbotthepony.mc.otm.menu.tech + +import net.minecraft.world.Container +import net.minecraft.world.SimpleContainer +import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting +import ru.dbotthepony.mc.otm.block.entity.tech.EnergyHatchBlockEntity +import ru.dbotthepony.mc.otm.block.entity.tech.MatterHatchBlockEntity +import ru.dbotthepony.mc.otm.capability.FlowDirection +import ru.dbotthepony.mc.otm.menu.BatterySlot +import ru.dbotthepony.mc.otm.menu.EnergyContainerInputSlot +import ru.dbotthepony.mc.otm.menu.MatterContainerInputSlot +import ru.dbotthepony.mc.otm.menu.MatteryMenu +import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback +import ru.dbotthepony.mc.otm.menu.makeSlots +import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget +import ru.dbotthepony.mc.otm.registry.MMenus + +class EnergyHatchMenu( + val isInput: Boolean, + containerId: Int, + inventory: Inventory, + tile: EnergyHatchBlockEntity? = null +) : MatteryMenu(if (isInput) MMenus.ENERGY_INPUT_HATCH else MMenus.ENERGY_OUTPUT_HATCH, containerId, inventory, tile) { + val container: Container = tile?.container ?: SimpleContainer(EnergyHatchBlockEntity.CAPACITY) + + val inputSlots = makeSlots(container) { a, b -> + EnergyContainerInputSlot(a, b, direction = FlowDirection.input(isInput)) + } + + val gauge = ProfiledLevelGaugeWidget(this, tile?.energy) + val redstone = EnumInputWithFeedback(this) + + init { + if (tile != null) + redstone.with(tile.redstoneControl::redstoneSetting) + + addStorageSlot(inputSlots) + addInventorySlots() + } + + companion object { + fun input(containerId: Int, inventory: Inventory, tile: EnergyHatchBlockEntity? = null): EnergyHatchMenu { + return EnergyHatchMenu(true, containerId, inventory, tile) + } + + fun output(containerId: Int, inventory: Inventory, tile: EnergyHatchBlockEntity? = null): EnergyHatchMenu { + return EnergyHatchMenu(false, containerId, inventory, tile) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ItemHatchMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ItemHatchMenu.kt new file mode 100644 index 000000000..2ddd294b6 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/ItemHatchMenu.kt @@ -0,0 +1,52 @@ +package ru.dbotthepony.mc.otm.menu.tech + +import com.google.common.collect.ImmutableList +import net.minecraft.world.Container +import net.minecraft.world.SimpleContainer +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.item.ItemStack +import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting +import ru.dbotthepony.mc.otm.block.entity.tech.ItemHatchBlockEntity +import ru.dbotthepony.mc.otm.menu.MatteryMenu +import ru.dbotthepony.mc.otm.menu.UserFilteredSlot +import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback +import ru.dbotthepony.mc.otm.menu.makeSlots +import ru.dbotthepony.mc.otm.registry.MMenus + +class ItemHatchMenu( + val isInput: Boolean, + containerId: Int, + inventory: Inventory, + tile: ItemHatchBlockEntity? = null +) : MatteryMenu(if (isInput) MMenus.ITEM_INPUT_HATCH else MMenus.ITEM_OUTPUT_HATCH, containerId, inventory, tile) { + val actualContainer: Container = tile?.container ?: SimpleContainer(ItemHatchBlockEntity.CAPACITY) + val storageSlots: ImmutableList = makeSlots(actualContainer) { a, b -> + object : UserFilteredSlot(a, b) { + override fun mayPlace(itemStack: ItemStack): Boolean { + return isInput && super.mayPlace(itemStack) + } + } + } + + val sort = SortInput(actualContainer, playerSortSettings) + val redstone = EnumInputWithFeedback(this) + + init { + if (tile != null) + redstone.with(tile.redstoneControl::redstoneSetting) + + sort.input.filter { isInput } + addStorageSlot(storageSlots) + addInventorySlots() + } + + companion object { + fun input(containerId: Int, inventory: Inventory, tile: ItemHatchBlockEntity? = null): ItemHatchMenu { + return ItemHatchMenu(true, containerId, inventory, tile) + } + + fun output(containerId: Int, inventory: Inventory, tile: ItemHatchBlockEntity? = null): ItemHatchMenu { + return ItemHatchMenu(false, containerId, inventory, tile) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/MatterHatchMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/MatterHatchMenu.kt new file mode 100644 index 000000000..173096250 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/MatterHatchMenu.kt @@ -0,0 +1,49 @@ +package ru.dbotthepony.mc.otm.menu.tech + +import net.minecraft.world.Container +import net.minecraft.world.SimpleContainer +import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting +import ru.dbotthepony.mc.otm.block.entity.tech.MatterHatchBlockEntity +import ru.dbotthepony.mc.otm.capability.FlowDirection +import ru.dbotthepony.mc.otm.menu.MatterContainerInputSlot +import ru.dbotthepony.mc.otm.menu.MatteryMenu +import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback +import ru.dbotthepony.mc.otm.menu.makeSlots +import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget +import ru.dbotthepony.mc.otm.registry.MMenus + +class MatterHatchMenu( + val isInput: Boolean, + containerId: Int, + inventory: Inventory, + tile: MatterHatchBlockEntity? = null +) : MatteryMenu(if (isInput) MMenus.MATTER_INPUT_HATCH else MMenus.MATTER_OUTPUT_HATCH, containerId, inventory, tile) { + val container: Container = tile?.container ?: SimpleContainer(MatterHatchBlockEntity.CAPACITY) + + val inputSlots = makeSlots(container) { a, b -> + MatterContainerInputSlot(a, b, direction = FlowDirection.input(isInput)) + } + + val gauge = ProfiledLevelGaugeWidget(this, tile?.matter) + val redstone = EnumInputWithFeedback(this) + + init { + if (tile != null) + redstone.with(tile.redstoneControl::redstoneSetting) + + addStorageSlot(inputSlots) + addInventorySlots() + } + + companion object { + fun input(containerId: Int, inventory: Inventory, tile: MatterHatchBlockEntity? = null): MatterHatchMenu { + return MatterHatchMenu(true, containerId, inventory, tile) + } + + fun output(containerId: Int, inventory: Inventory, tile: MatterHatchBlockEntity? = null): MatterHatchMenu { + return MatterHatchMenu(false, containerId, inventory, tile) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt index 4db354925..27aea31ec 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlockEntities.kt @@ -6,10 +6,7 @@ import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent -import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.ForgeRegistries -import net.minecraftforge.registries.RegistryObject -import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.block.entity.* import ru.dbotthepony.mc.otm.block.entity.tech.* import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity @@ -23,6 +20,7 @@ import ru.dbotthepony.mc.otm.block.entity.decorative.HoloSignBlockEntity import ru.dbotthepony.mc.otm.block.entity.decorative.InfiniteWaterSourceBlockEntity import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity import ru.dbotthepony.mc.otm.block.entity.matter.* +import ru.dbotthepony.mc.otm.block.entity.tech.ItemHatchBlockEntity import ru.dbotthepony.mc.otm.block.entity.storage.* import ru.dbotthepony.mc.otm.block.entity.tech.AndroidStationBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.BatteryBankBlockEntity @@ -31,9 +29,7 @@ import ru.dbotthepony.mc.otm.block.entity.tech.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity import ru.dbotthepony.mc.otm.client.render.blockentity.* import ru.dbotthepony.mc.otm.config.CablesConfig -import ru.dbotthepony.mc.otm.core.asSupplierArray import ru.dbotthepony.mc.otm.core.collect.SupplierMap -import ru.dbotthepony.mc.otm.core.getValue import java.util.function.Supplier @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") // Type<*> is unused in BlockEntityType.Builder @@ -86,6 +82,13 @@ object MBlockEntities { val DEV_CHEST by register(MNames.DEV_CHEST, ::DevChestBlockEntity, MBlocks::DEV_CHEST) val PAINTER by register(MNames.PAINTER, ::PainterBlockEntity, MBlocks::PAINTER) val MATTER_ENTANGLER by register(MNames.MATTER_ENTANGLER, ::MatterEntanglerBlockEntity, MBlocks::MATTER_ENTANGLER) + val BLACK_HOLE_GENERATOR by register(MNames.BLACK_HOLE_GENERATOR, ::BlackHoleGeneratorBlockEntity, MBlocks::BLACK_HOLE_GENERATOR) + val ITEM_INPUT_HATCH by register(MNames.ITEM_INPUT_HATCH, ItemHatchBlockEntity::input, MBlocks::ITEM_INPUT_HATCH) + val ITEM_OUTPUT_HATCH by register(MNames.ITEM_OUTPUT_HATCH, ItemHatchBlockEntity::output, MBlocks::ITEM_OUTPUT_HATCH) + val ENERGY_INPUT_HATCH by register(MNames.ENERGY_INPUT_HATCH, EnergyHatchBlockEntity::input, MBlocks::ENERGY_INPUT_HATCH) + val ENERGY_OUTPUT_HATCH by register(MNames.ENERGY_OUTPUT_HATCH, EnergyHatchBlockEntity::output, MBlocks::ENERGY_OUTPUT_HATCH) + val MATTER_INPUT_HATCH by register(MNames.MATTER_INPUT_HATCH, MatterHatchBlockEntity::input, MBlocks::MATTER_INPUT_HATCH) + val MATTER_OUTPUT_HATCH by register(MNames.MATTER_OUTPUT_HATCH, MatterHatchBlockEntity::output, MBlocks::MATTER_OUTPUT_HATCH) val POWERED_FURNACE by register(MNames.POWERED_FURNACE, ::PoweredFurnaceBlockEntity, MBlocks.POWERED_FURNACE) val POWERED_BLAST_FURNACE by register(MNames.POWERED_BLAST_FURNACE, ::PoweredBlastFurnaceBlockEntity, MBlocks.POWERED_BLAST_FURNACE) @@ -93,9 +96,9 @@ object MBlockEntities { val MULTIBLOCK_TEST by register("multiblock_test", ::MultiblockTestBlockEntity, MBlocks::MULTIBLOCK_TEST) - val ENERGY_CABLES: Map> = SupplierMap(CablesConfig.E.entries.map { conf -> - var selfFeed: Supplier> = Supplier { TODO() } - selfFeed = register("${conf.name.lowercase()}_energy_cable", { a, b -> SimpleEnergyCableBlockEntity(selfFeed.get(), a, b, conf) }) as Supplier> + val ENERGY_CABLES: Map> = SupplierMap(CablesConfig.E.entries.map { conf -> + var selfFeed: Supplier> = Supplier { TODO() } + selfFeed = register("${conf.name.lowercase()}_energy_cable", { a, b -> SimpleEnergyCableBlockEntity(selfFeed.get(), a, b, conf) }) conf to selfFeed }) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt index 14c471d08..ac49301a8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt @@ -1,8 +1,6 @@ package ru.dbotthepony.mc.otm.registry import net.minecraft.util.valueproviders.UniformInt -import net.minecraft.world.item.DyeColor -import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.level.block.AnvilBlock import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.DropExperienceBlock @@ -18,9 +16,7 @@ import net.minecraft.world.level.block.state.properties.NoteBlockInstrument import net.minecraft.world.level.material.MapColor import net.minecraft.world.level.material.PushReaction import net.minecraftforge.eventbus.api.IEventBus -import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.ForgeRegistries -import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.block.BlackHoleBlock import ru.dbotthepony.mc.otm.block.BlockExplosionDebugger import ru.dbotthepony.mc.otm.block.BlockSphereDebugger @@ -28,6 +24,7 @@ import ru.dbotthepony.mc.otm.block.EnergyCableBlock import ru.dbotthepony.mc.otm.block.MatterCableBlock import ru.dbotthepony.mc.otm.block.MatteryBlock import ru.dbotthepony.mc.otm.block.MultiblockTestBlock +import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.StorageCableBlock import ru.dbotthepony.mc.otm.block.addSimpleDescription import ru.dbotthepony.mc.otm.block.decorative.DevChestBlock @@ -40,6 +37,9 @@ import ru.dbotthepony.mc.otm.block.decorative.LaboratoryLampLight import ru.dbotthepony.mc.otm.block.decorative.PainterBlock import ru.dbotthepony.mc.otm.block.decorative.TritaniumDoorBlock import ru.dbotthepony.mc.otm.block.decorative.TritaniumTrapdoorBlock +import ru.dbotthepony.mc.otm.block.entity.tech.EnergyHatchBlockEntity +import ru.dbotthepony.mc.otm.block.entity.tech.ItemHatchBlockEntity +import ru.dbotthepony.mc.otm.block.entity.tech.MatterHatchBlockEntity import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock import ru.dbotthepony.mc.otm.block.matter.MatterCapacitorBankBlock import ru.dbotthepony.mc.otm.block.matter.MatterDecomposerBlock @@ -50,6 +50,7 @@ import ru.dbotthepony.mc.otm.block.matter.MatterRecyclerBlock import ru.dbotthepony.mc.otm.block.matter.MatterReplicatorBlock import ru.dbotthepony.mc.otm.block.matter.MatterScannerBlock import ru.dbotthepony.mc.otm.block.matter.PatternStorageBlock +import ru.dbotthepony.mc.otm.block.tech.HatchBlock import ru.dbotthepony.mc.otm.block.storage.DriveRackBlock import ru.dbotthepony.mc.otm.block.storage.DriveViewerBlock import ru.dbotthepony.mc.otm.block.storage.ItemMonitorBlock @@ -60,6 +61,7 @@ import ru.dbotthepony.mc.otm.block.storage.StoragePowerSupplierBlock import ru.dbotthepony.mc.otm.block.tech.AndroidChargerBlock import ru.dbotthepony.mc.otm.block.tech.AndroidStationBlock import ru.dbotthepony.mc.otm.block.tech.BatteryBankBlock +import ru.dbotthepony.mc.otm.block.tech.BlackHoleGeneratorBlock import ru.dbotthepony.mc.otm.block.tech.BlockGravitationStabilizer import ru.dbotthepony.mc.otm.block.tech.BlockGravitationStabilizerLens import ru.dbotthepony.mc.otm.block.tech.ChemicalGeneratorBlock @@ -69,15 +71,12 @@ import ru.dbotthepony.mc.otm.block.tech.EnergyServoBlock import ru.dbotthepony.mc.otm.block.tech.EssenceStorageBlock import ru.dbotthepony.mc.otm.block.tech.PhantomAttractorBlock import ru.dbotthepony.mc.otm.block.tech.PlatePressBlock -import ru.dbotthepony.mc.otm.block.tech.AbstractPoweredFurnaceBlock import ru.dbotthepony.mc.otm.block.tech.PoweredBlastFurnaceBlock import ru.dbotthepony.mc.otm.block.tech.PoweredFurnaceBlock import ru.dbotthepony.mc.otm.block.tech.PoweredSmokerBlock import ru.dbotthepony.mc.otm.config.CablesConfig -import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.mc.otm.core.collect.SupplierList import ru.dbotthepony.mc.otm.core.collect.SupplierMap -import ru.dbotthepony.mc.otm.shapes.BlockShapes import java.util.function.Supplier object MBlocks { @@ -139,6 +138,18 @@ object MBlocks { val FLUID_TANK: FluidTankBlock by registry.register(MNames.FLUID_TANK) { FluidTankBlock() } val DEV_CHEST: DevChestBlock by registry.register(MNames.DEV_CHEST) { DevChestBlock() } + val MULTIBLOCK_STRUCTURE by registry.register(MNames.MULTIBLOCK_STRUCTURE) { MatteryBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } + val BLACK_HOLE_GENERATOR by registry.register(MNames.BLACK_HOLE_GENERATOR) { BlackHoleGeneratorBlock() } + val MATTER_INJECTOR by registry.register(MNames.MATTER_INJECTOR) { RotatableMatteryBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } + val ANTIMATTER_INJECTOR by registry.register(MNames.ANTIMATTER_INJECTOR) { RotatableMatteryBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } + val HIGH_ENERGY_PARTICLE_COLLECTOR by registry.register(MNames.HIGH_ENERGY_PARTICLE_COLLECTOR) { RotatableMatteryBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } + val ITEM_INPUT_HATCH by registry.register(MNames.ITEM_INPUT_HATCH) { HatchBlock(ItemHatchBlockEntity::input) } + val ITEM_OUTPUT_HATCH by registry.register(MNames.ITEM_OUTPUT_HATCH) { HatchBlock(ItemHatchBlockEntity::output) } + val ENERGY_INPUT_HATCH by registry.register(MNames.ENERGY_INPUT_HATCH) { HatchBlock(EnergyHatchBlockEntity::input) } + val ENERGY_OUTPUT_HATCH by registry.register(MNames.ENERGY_OUTPUT_HATCH) { HatchBlock(EnergyHatchBlockEntity::output) } + val MATTER_INPUT_HATCH by registry.register(MNames.MATTER_INPUT_HATCH) { HatchBlock(MatterHatchBlockEntity::input, true) } + val MATTER_OUTPUT_HATCH by registry.register(MNames.MATTER_OUTPUT_HATCH) { HatchBlock(MatterHatchBlockEntity::output, true) } + val LIQUID_XP: LiquidBlock by registry.register("liquid_xp") { LiquidBlock(MFluids::LIQUID_XP, BlockBehaviour.Properties.of().mapColor(MapColor.EMERALD).replaceable().noCollission().strength(100.0f).pushReaction(PushReaction.DESTROY).noLootTable().liquid().sound(SoundType.EMPTY)) } val TRITANIUM_ORE: Block by registry.register(MNames.TRITANIUM_ORE) { DropExperienceBlock( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt index 96dc11e0a..b006169ff 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt @@ -110,6 +110,14 @@ object MItems { val PAINTER: BlockItem by registry.register(MNames.PAINTER) { BlockItem(MBlocks.PAINTER, DEFAULT_PROPERTIES) } val MATTER_ENTANGLER: BlockItem by registry.register(MNames.MATTER_ENTANGLER) { BlockItem(MBlocks.MATTER_ENTANGLER, DEFAULT_PROPERTIES) } + val BLACK_HOLE_GENERATOR by registry.register(MNames.BLACK_HOLE_GENERATOR) { BlockItem(MBlocks.BLACK_HOLE_GENERATOR, DEFAULT_PROPERTIES) } + val ITEM_INPUT_HATCH by registry.register(MNames.ITEM_INPUT_HATCH) { BlockItem(MBlocks.ITEM_INPUT_HATCH, DEFAULT_PROPERTIES) } + val ITEM_OUTPUT_HATCH by registry.register(MNames.ITEM_OUTPUT_HATCH) { BlockItem(MBlocks.ITEM_OUTPUT_HATCH, DEFAULT_PROPERTIES) } + val ENERGY_INPUT_HATCH by registry.register(MNames.ENERGY_INPUT_HATCH) { BlockItem(MBlocks.ENERGY_INPUT_HATCH, DEFAULT_PROPERTIES) } + val ENERGY_OUTPUT_HATCH by registry.register(MNames.ENERGY_OUTPUT_HATCH) { BlockItem(MBlocks.ENERGY_OUTPUT_HATCH, DEFAULT_PROPERTIES) } + val MATTER_INPUT_HATCH by registry.register(MNames.MATTER_INPUT_HATCH) { BlockItem(MBlocks.MATTER_INPUT_HATCH, DEFAULT_PROPERTIES) } + val MATTER_OUTPUT_HATCH by registry.register(MNames.MATTER_OUTPUT_HATCH) { BlockItem(MBlocks.MATTER_OUTPUT_HATCH, DEFAULT_PROPERTIES) } + val MACHINES: List init { @@ -146,6 +154,14 @@ object MItems { machines.add(::GRAVITATION_STABILIZER) + machines.add(::BLACK_HOLE_GENERATOR) + machines.add(::ITEM_INPUT_HATCH) + machines.add(::ITEM_OUTPUT_HATCH) + machines.add(::ENERGY_INPUT_HATCH) + machines.add(::ENERGY_OUTPUT_HATCH) + machines.add(::MATTER_INPUT_HATCH) + machines.add(::MATTER_OUTPUT_HATCH) + machines.add(::STORAGE_BUS) machines.add(::STORAGE_IMPORTER) machines.add(::STORAGE_EXPORTER) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MMenus.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MMenus.kt index abbb2dd6b..6beedd44e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MMenus.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MMenus.kt @@ -37,6 +37,9 @@ import ru.dbotthepony.mc.otm.client.screen.tech.EnergyServoScreen import ru.dbotthepony.mc.otm.client.screen.tech.EssenceStorageScreen import ru.dbotthepony.mc.otm.client.screen.decorative.PainterScreen import ru.dbotthepony.mc.otm.client.screen.tech.AbstractProcessingMachineScreen +import ru.dbotthepony.mc.otm.client.screen.tech.EnergyHatchScreen +import ru.dbotthepony.mc.otm.client.screen.tech.ItemHatchScreen +import ru.dbotthepony.mc.otm.client.screen.tech.MatterHatchScreen import ru.dbotthepony.mc.otm.menu.decorative.CargoCrateMenu import ru.dbotthepony.mc.otm.menu.decorative.FluidTankMenu import ru.dbotthepony.mc.otm.menu.decorative.HoloSignMenu @@ -66,6 +69,9 @@ import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu import ru.dbotthepony.mc.otm.menu.tech.EnergyServoMenu import ru.dbotthepony.mc.otm.menu.tech.EssenceStorageMenu import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu +import ru.dbotthepony.mc.otm.menu.tech.EnergyHatchMenu +import ru.dbotthepony.mc.otm.menu.tech.ItemHatchMenu +import ru.dbotthepony.mc.otm.menu.tech.MatterHatchMenu import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu @@ -103,6 +109,12 @@ object MMenus { val FLUID_TANK by registry.register(MNames.FLUID_TANK) { MenuType(::FluidTankMenu, FeatureFlags.VANILLA_SET) } val PAINTER by registry.register(MNames.PAINTER) { MenuType(::PainterMenu, FeatureFlags.VANILLA_SET) } val MATTER_ENTANGLER by registry.register(MNames.MATTER_ENTANGLER) { MenuType(::MatterEntanglerMenu, FeatureFlags.VANILLA_SET) } + val ITEM_INPUT_HATCH by registry.register(MNames.ITEM_INPUT_HATCH) { MenuType(ItemHatchMenu::input, FeatureFlags.VANILLA_SET) } + val ITEM_OUTPUT_HATCH by registry.register(MNames.ITEM_OUTPUT_HATCH) { MenuType(ItemHatchMenu::output, FeatureFlags.VANILLA_SET) } + val MATTER_INPUT_HATCH by registry.register(MNames.MATTER_INPUT_HATCH) { MenuType(MatterHatchMenu::input, FeatureFlags.VANILLA_SET) } + val MATTER_OUTPUT_HATCH by registry.register(MNames.MATTER_OUTPUT_HATCH) { MenuType(MatterHatchMenu::output, FeatureFlags.VANILLA_SET) } + val ENERGY_INPUT_HATCH by registry.register(MNames.ENERGY_INPUT_HATCH) { MenuType(EnergyHatchMenu::input, FeatureFlags.VANILLA_SET) } + val ENERGY_OUTPUT_HATCH by registry.register(MNames.ENERGY_OUTPUT_HATCH) { MenuType(EnergyHatchMenu::output, FeatureFlags.VANILLA_SET) } val STORAGE_BUS by registry.register(MNames.STORAGE_BUS) { MenuType(::StorageBusMenu, FeatureFlags.VANILLA_SET) } val STORAGE_IMPORTER_EXPORTER by registry.register(MNames.STORAGE_IMPORTER) { MenuType(::StorageImporterExporterMenu, FeatureFlags.VANILLA_SET) } @@ -149,6 +161,12 @@ object MMenus { MenuScreens.register(POWERED_SMOKER, ::AbstractProcessingMachineScreen) MenuScreens.register(PAINTER, ::PainterScreen) MenuScreens.register(MATTER_ENTANGLER, ::MatterEntanglerScreen) + MenuScreens.register(ITEM_INPUT_HATCH, ::ItemHatchScreen) + MenuScreens.register(ITEM_OUTPUT_HATCH, ::ItemHatchScreen) + MenuScreens.register(MATTER_INPUT_HATCH, ::MatterHatchScreen) + MenuScreens.register(MATTER_OUTPUT_HATCH, ::MatterHatchScreen) + MenuScreens.register(ENERGY_INPUT_HATCH, ::EnergyHatchScreen) + MenuScreens.register(ENERGY_OUTPUT_HATCH, ::EnergyHatchScreen) } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt index 258cc69c5..a36344d2c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt @@ -15,6 +15,17 @@ object MNames { const val ANDROID_CHARGER = "android_charger" const val INFINITE_WATER_SOURCE = "infinite_water_source" const val DEV_CHEST = "dev_chest" + const val MULTIBLOCK_STRUCTURE = "black_hole_generator" + const val BLACK_HOLE_GENERATOR = "black_hole_generator" + const val MATTER_INJECTOR = "matter_injector" + const val ANTIMATTER_INJECTOR = "antimatter_injector" + const val HIGH_ENERGY_PARTICLE_COLLECTOR = "high_energy_particle_collector" + const val ITEM_INPUT_HATCH = "item_input_hatch" + const val ITEM_OUTPUT_HATCH = "item_output_hatch" + const val ENERGY_INPUT_HATCH = "energy_input_hatch" + const val ENERGY_OUTPUT_HATCH = "energy_output_hatch" + const val MATTER_INPUT_HATCH = "matter_input_hatch" + const val MATTER_OUTPUT_HATCH = "matter_output_hatch" const val PAINTER = "painter" const val MATTER_ENTANGLER = "matter_entangler" From 82bb39aded708ed0ef7a0ab76f767e0f5ddeee32 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 15 Feb 2024 18:52:42 +0700 Subject: [PATCH 19/38] Add kommons to dependencies --- build.gradle.kts | 6 ++++++ gradle.properties | 2 ++ 2 files changed, 8 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 73f500b41..6533c8e0d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -123,12 +123,17 @@ dependencies { val jupiter_version: String by project val kotlin_for_forge_version: String by project val mixin_version: String by project + val kommons_version: String by project minecraft("net.minecraftforge:forge:$mc_version-$forge_version") testImplementation("org.junit.jupiter:junit-jupiter:${jupiter_version}") implementation("thedarkcolour:kotlinforforge:$kotlin_for_forge_version") + implementation("ru.dbotthepony.kommons:kommons:$kommons_version") + implementation("ru.dbotthepony.kommons:kommons-gson:$kommons_version") + implementation("ru.dbotthepony.kommons:kommons-guava:$kommons_version") + compileOnly("yalter.mousetweaks:MouseTweaks:2.23:api") annotationProcessor("org.spongepowered:mixin:${mixin_version}:processor") @@ -272,6 +277,7 @@ repositories { includeGroup("at.ridgo8.moreoverlays") includeGroup("ru.dbotthepony") includeGroup("curse.maven") + includeGroup("ru.dbotthepony.kommons") } } diff --git a/gradle.properties b/gradle.properties index b6e738d91..3d43496b2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,6 +19,8 @@ forge_version=48.1.0 mixingradle_version=0.7.33 mixin_version=0.8.5 +kommons_version=2.3.2 + jei_version=16.0.0.28 jupiter_version=5.9.2 curios_version=6.0.2 From 22430cd9372641efc355e3c9a556f2395c3727aa Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 15 Feb 2024 19:49:05 +0700 Subject: [PATCH 20/38] Actually add kommons to dependencies --- build.gradle.kts | 27 ++++++++++++++++--- gradle.properties | 2 +- .../ru/dbotthepony/mc/otm/registry/MNames.kt | 2 +- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6533c8e0d..88b8b4f17 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,6 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.util.Date import java.text.SimpleDateFormat import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream +import org.gradle.kotlin.dsl.accessors.runtime.addDependencyTo val mod_version: String by project val mc_version: String by project @@ -119,6 +120,12 @@ tasks.test { useJUnitPlatform() } +configurations { + create("embeddedLibs") +} + +jarJar.enable() + dependencies { val jupiter_version: String by project val kotlin_for_forge_version: String by project @@ -130,9 +137,17 @@ dependencies { implementation("thedarkcolour:kotlinforforge:$kotlin_for_forge_version") - implementation("ru.dbotthepony.kommons:kommons:$kommons_version") - implementation("ru.dbotthepony.kommons:kommons-gson:$kommons_version") - implementation("ru.dbotthepony.kommons:kommons-guava:$kommons_version") + jarJar("ru.dbotthepony.kommons:kommons:[$kommons_version,)") { setTransitive(false) } + 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) } + + minecraftLibrary("ru.dbotthepony.kommons:kommons:[$kommons_version,)") { setTransitive(false) } + minecraftLibrary("ru.dbotthepony.kommons:kommons-gson:[$kommons_version,)") { setTransitive(false) } + minecraftLibrary("ru.dbotthepony.kommons:kommons-guava:[$kommons_version,)") { setTransitive(false) } compileOnly("yalter.mousetweaks:MouseTweaks:2.23:api") annotationProcessor("org.spongepowered:mixin:${mixin_version}:processor") @@ -331,6 +346,12 @@ fun org.gradle.jvm.tasks.Jar.attachManifest() { tasks.jar.configure { finalizedBy("reobfJar") attachManifest() + archiveClassifier.set("slim") + archiveVersion.set(gitVersion.jarName) +} + +tasks.jarJar.configure { + archiveClassifier.set("") archiveVersion.set(gitVersion.jarName) } diff --git a/gradle.properties b/gradle.properties index 3d43496b2..f8f2d4aae 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.2 +kommons_version=2.3.3 jei_version=16.0.0.28 jupiter_version=5.9.2 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt index a36344d2c..ffaf11717 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt @@ -15,7 +15,7 @@ object MNames { const val ANDROID_CHARGER = "android_charger" const val INFINITE_WATER_SOURCE = "infinite_water_source" const val DEV_CHEST = "dev_chest" - const val MULTIBLOCK_STRUCTURE = "black_hole_generator" + const val MULTIBLOCK_STRUCTURE = "multiblock_structure" const val BLACK_HOLE_GENERATOR = "black_hole_generator" const val MATTER_INJECTOR = "matter_injector" const val ANTIMATTER_INJECTOR = "antimatter_injector" From 2fbce58148c4d43fc5e170554430e6ea07de888f Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sun, 25 Feb 2024 18:30:25 +0700 Subject: [PATCH 21/38] Migrate to DelegateSyncher and Delegate<> --- build.gradle.kts | 6 +- gradle.properties | 2 +- .../mc/otm/android/AndroidFeature.kt | 19 +- .../mc/otm/android/AndroidResearch.kt | 16 +- .../otm/android/AndroidResearchDescription.kt | 1 + .../mc/otm/android/AndroidResearchResult.kt | 1 + .../otm/android/AndroidSwitchableFeature.kt | 17 +- .../android/feature/EnderTeleporterFeature.kt | 2 +- .../otm/android/feature/ItemMagnetFeature.kt | 2 +- .../otm/android/feature/JumpBoostFeature.kt | 12 +- .../android/feature/NanobotsArmorFeature.kt | 17 +- .../otm/android/feature/NightVisionFeature.kt | 2 +- .../otm/android/feature/ShockwaveFeature.kt | 2 +- .../otm/android/feature/StepAssistFeature.kt | 2 +- .../android/feature/SwimBoostersFeature.kt | 2 +- .../mc/otm/block/entity/MatteryBlockEntity.kt | 150 +- .../block/entity/MatteryDeviceBlockEntity.kt | 55 +- .../mc/otm/block/entity/RedstoneControl.kt | 63 +- .../entity/blackhole/BlackHoleBlockEntity.kt | 17 +- .../entity/cable/EnergyCableBlockEntity.kt | 6 +- .../entity/decorative/FluidTankBlockEntity.kt | 10 +- .../entity/decorative/HoloSignBlockEntity.kt | 29 +- .../InfiniteWaterSourceBlockEntity.kt | 3 +- .../matter/MatterCapacitorBankBlockEntity.kt | 9 +- .../matter/MatterReconstructorBlockEntity.kt | 5 +- .../matter/MatterReplicatorBlockEntity.kt | 7 +- .../entity/matter/MatterScannerBlockEntity.kt | 7 +- .../entity/storage/DriveRackBlockEntity.kt | 5 +- .../entity/storage/StorageBusBlockEntity.kt | 11 +- .../tech/AbstractPoweredFurnaceBlockEntity.kt | 10 +- .../entity/tech/BatteryBankBlockEntity.kt | 9 +- .../entity/tech/EnergyCounterBlockEntity.kt | 7 +- .../otm/capability/MatteryPlayerCapability.kt | 129 +- .../energy/BatteryBackedEnergyStorage.kt | 12 +- .../energy/IMatteryEnergyStorage.kt | 2 +- .../fluid/BlockMatteryFluidHandler.kt | 6 +- .../otm/capability/matter/IMatterStorage.kt | 2 +- .../otm/capability/matter/IPatternStorage.kt | 2 +- .../mc/otm/client/AndroidAbilityKeyMapping.kt | 2 +- .../mc/otm/client/AndroidMenuKeyMapping.kt | 2 +- .../dbotthepony/mc/otm/client/MatteryGUI.kt | 2 +- .../mc/otm/client/render/FontRenderer.kt | 2 +- .../mc/otm/client/render/IGUIRenderable.kt | 2 +- .../mc/otm/client/render/MGUIGraphics.kt | 2 +- .../mc/otm/client/render/RenderExtensions.kt | 2 +- .../mc/otm/client/render/RenderHelper.kt | 2 +- .../client/render/blockentity/BankRenderer.kt | 11 +- .../render/blockentity/BlackHoleRenderer.kt | 2 +- .../blockentity/EnergyCounterRenderer.kt | 2 +- .../render/blockentity/FluidTankRenderer.kt | 2 +- .../GravitationStabilizerRenderer.kt | 2 +- .../render/blockentity/HoloSignRenderer.kt | 2 +- .../render/sprites/AbstractMatterySprite.kt | 2 +- .../mc/otm/client/screen/MatteryScreen.kt | 2 + .../screen/decorative/HoloSignScreen.kt | 2 +- .../client/screen/decorative/PainterScreen.kt | 8 +- .../client/screen/matter/MatterPanelScreen.kt | 8 +- .../otm/client/screen/panels/ColorPicker.kt | 4 +- .../client/screen/panels/EffectListPanel.kt | 2 +- .../screen/panels/EntityRendererPanel.kt | 8 +- .../mc/otm/client/screen/panels/FramePanel.kt | 2 +- .../mc/otm/client/screen/panels/Label.kt | 2 +- .../button/BooleanRectangleButtonPanel.kt | 6 +- .../screen/panels/button/ButtonPanel.kt | 2 +- .../client/screen/panels/button/Buttons.kt | 13 +- .../panels/button/CheckBoxInputPanel.kt | 3 - .../panels/button/CheckBoxLabelPanel.kt | 4 +- .../screen/panels/button/CheckBoxPanel.kt | 4 +- .../panels/button/EnumRectangleButtonPanel.kt | 8 +- .../LargeBooleanRectangleButtonPanel.kt | 4 +- .../button/LargeEnumRectangleButtonPanel.kt | 6 +- .../button/LargeRectangleButtonPanel.kt | 2 +- .../SmallBooleanRectangleButtonPanel.kt | 4 +- .../button/SmallEnumRectangleButtonPanel.kt | 4 +- .../panels/input/NetworkNumberInputPanel.kt | 13 +- .../screen/panels/input/NumberInputPanel.kt | 10 +- .../screen/panels/input/TextInputPanel.kt | 2 +- .../screen/panels/slot/AbstractSlotPanel.kt | 2 +- .../screen/panels/slot/FilterSlotPanel.kt | 4 +- .../panels/slot/UserFilteredSlotPanel.kt | 8 +- .../screen/storage/DriveViewerScreen.kt | 4 +- .../screen/storage/ItemMonitorScreen.kt | 10 +- .../screen/tech/AndroidStationScreen.kt | 2 +- .../client/screen/widget/FluidGaugePanel.kt | 2 +- .../client/screen/widget/MatterGaugePanel.kt | 1 + .../client/screen/widget/PowerGaugePanel.kt | 1 + .../mc/otm/compat/jade/JadeCompatData.kt | 2 +- .../jade/providers/MatterBottlerProvider.kt | 2 +- .../providers/MatterReconstructorProvider.kt | 2 +- .../jade/providers/MatterStorageProvider.kt | 2 +- .../jade/providers/MatteryEnergyProvider.kt | 2 +- .../jade/providers/MatteryWorkerProvider.kt | 2 +- .../otm/compat/jei/MicrowaveRecipeCategory.kt | 2 +- .../compat/jei/PlatePressRecipeCategory.kt | 2 +- .../mc/otm/compat/vanilla/MatteryChestMenu.kt | 1 + .../mc/otm/config/AbstractConfig.kt | 11 +- .../mc/otm/config/AndroidConfig.kt | 1 + .../dbotthepony/mc/otm/config/CablesConfig.kt | 2 + .../mc/otm/config/ExopackConfig.kt | 1 + .../dbotthepony/mc/otm/config/ItemsConfig.kt | 1 + .../mc/otm/config/MachinesConfig.kt | 1 + .../mc/otm/config/ObservedConfigValue.kt | 16 +- .../mc/otm/container/MatteryContainer.kt | 56 +- .../mc/otm/container/util/Iterators.kt | 5 +- .../kotlin/ru/dbotthepony/mc/otm/core/Ext.kt | 10 + .../dbotthepony/mc/otm/core/GetterSetter.kt | 148 -- .../dbotthepony/mc/otm/core/ISubscripable.kt | 300 --- .../ru/dbotthepony/mc/otm/core/math/Colors.kt | 397 +-- .../otm/core/util/CounterInvalidatedLazy.kt | 2 +- .../mc/otm/core/util/IntCounter.kt | 18 +- .../mc/otm/core/util/Savetables.kt | 66 +- .../mc/otm/core/util/StreamCodecs.kt | 218 +- .../mc/otm/item/armor/TritaniumArmorItem.kt | 2 +- .../mc/otm/item/weapon/AbstractWeaponItem.kt | 4 +- .../mc/otm/matter/IMatterFunction.kt | 1 + .../mc/otm/menu/ISortingSettings.kt | 18 +- .../ru/dbotthepony/mc/otm/menu/MatteryMenu.kt | 88 +- .../ru/dbotthepony/mc/otm/menu/Slots.kt | 5 +- .../mc/otm/menu/decorative/CargoCrateMenu.kt | 5 - .../menu/decorative/MinecartCargoCrateMenu.kt | 2 - .../mc/otm/menu/decorative/PainterMenu.kt | 15 +- .../input/AbstractPlayerInputWithFeedback.kt | 17 +- .../menu/input/BooleanInputWithFeedback.kt | 8 +- .../otm/menu/input/EnergyConfigPlayerInput.kt | 4 +- .../otm/menu/input/EnumInputWithFeedback.kt | 16 +- .../otm/menu/input/FloatInputWithFeedback.kt | 4 +- .../otm/menu/input/FluidConfigPlayerInput.kt | 4 +- .../mc/otm/menu/input/InstantBooleanInput.kt | 4 +- .../mc/otm/menu/input/IntInputWithFeedback.kt | 6 +- .../otm/menu/input/ItemConfigPlayerInput.kt | 8 +- .../otm/menu/input/StringInputWithFeedback.kt | 4 +- .../mc/otm/menu/matter/MatterPanelMenu.kt | 8 +- .../mc/otm/menu/storage/DriveViewerMenu.kt | 24 +- .../mc/otm/menu/storage/ItemMonitorMenu.kt | 6 +- .../menu/storage/StoragePowerSupplierMenu.kt | 3 + .../mc/otm/menu/tech/ChemicalGeneratorMenu.kt | 4 +- .../mc/otm/menu/tech/EnergyCounterMenu.kt | 14 +- .../mc/otm/menu/tech/EssenceStorageMenu.kt | 4 +- .../mc/otm/menu/widget/FluidGaugeWidget.kt | 11 +- .../mc/otm/menu/widget/LevelGaugeWidget.kt | 17 +- .../menu/widget/ProfiledLevelGaugeWidget.kt | 18 +- .../mc/otm/menu/widget/ProgressGaugeWidget.kt | 15 +- .../mc/otm/network/GenericNetworkChannel.kt | 6 +- .../mc/otm/network/MatteryNetworkChannel.kt | 8 +- .../network/MatteryPlayerNetworkChannel.kt | 6 +- .../network/synchronizer/ChangesetAction.kt | 5 - .../otm/network/synchronizer/FieldAccess.kt | 41 - .../otm/network/synchronizer/FieldGetter.kt | 50 - .../otm/network/synchronizer/FieldSetter.kt | 50 - .../network/synchronizer/FieldSynchronizer.kt | 2190 ----------------- .../mc/otm/network/synchronizer/Fields.kt | 173 -- .../otm/network/synchronizer/MapChangeset.kt | 23 - .../otm/network/synchronizer/MutableFields.kt | 166 -- .../otm/network/synchronizer/SetChangeset.kt | 22 - .../mc/otm/registry/MBlockColors.kt | 2 +- .../dbotthepony/mc/otm/registry/MRegistry.kt | 2 +- .../mc/otm/storage/ItemStorageStack.kt | 1 + .../mc/otm/storage/StorageStack.kt | 1 + .../mc/otm/tests/FieldSynchronizerTests.kt | 134 - 159 files changed, 769 insertions(+), 4575 deletions(-) delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/core/ISubscripable.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/ChangesetAction.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldAccess.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldGetter.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSetter.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/Fields.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/MapChangeset.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/MutableFields.kt delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/SetChangeset.kt delete mode 100644 src/test/kotlin/ru/dbotthepony/mc/otm/tests/FieldSynchronizerTests.kt 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) - } - } -} From e047341cdb59278f4271561ba493870a1f437e15 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sun, 25 Feb 2024 19:36:21 +0700 Subject: [PATCH 22/38] Specify Kommons as minecraft mod --- build.gradle.kts | 13 ++----------- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 25739d3b9..0559d7fde 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -137,17 +137,8 @@ dependencies { implementation("thedarkcolour:kotlinforforge:$kotlin_for_forge_version") - jarJar("ru.dbotthepony.kommons:kommons:[$kommons_version,)") { setTransitive(false) } - jarJar("ru.dbotthepony.kommons:kommons-gson:[$kommons_version,)") { setTransitive(false) } - jarJar("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) } - minecraftLibrary("ru.dbotthepony.kommons:kommons-guava:[$kommons_version,)") { setTransitive(false) } + jarJar("ru.dbotthepony.kommons:kommons-mc:[$kommons_version,)") { setTransitive(false) } + implementation("ru.dbotthepony.kommons:kommons-mc:[$kommons_version,)") { setTransitive(false) } compileOnly("yalter.mousetweaks:MouseTweaks:2.23:api") annotationProcessor("org.spongepowered:mixin:${mixin_version}:processor") diff --git a/gradle.properties b/gradle.properties index 4ba2fd72b..5024d8440 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.9.13 +kommons_version=2.9.15 jei_version=16.0.0.28 jupiter_version=5.9.2 From e63cce63ff92dd380e67fc8d2f0cf9b160df60bc Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sun, 25 Feb 2024 19:44:50 +0700 Subject: [PATCH 23/38] Call DelegateSyncher.observe --- src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt | 1 + .../kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt | 1 + .../ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt | 2 ++ src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt | 1 + 4 files changed, 5 insertions(+) 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 0fc28fa04..9fa3c0348 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt @@ -41,6 +41,7 @@ abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: Matt open fun onAttack(event: LivingAttackEvent) {} open fun collectNetworkPayload(): FastByteArrayOutputStream? { + syncher.observe() return syncherRemote.write() } 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 35dd6c40d..30c5a743e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt @@ -189,6 +189,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay } fun collectNetworkPayload(): FastByteArrayOutputStream? { + syncher.observe() return syncherRemote.write() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt index e8639bb66..ff83d23de 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -1329,6 +1329,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial tickedOnce = true + syncher.observe() + publicSyncher.observe() val payload = privateSyncherRemote.write() if (payload != null) { 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 577b9c11e..ef2290397 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -383,6 +383,7 @@ abstract class MatteryMenu( protected fun matteryBroadcast() { beforeBroadcast() + mSynchronizer.observe() val payload = synchronizerRemote.write() if (payload != null) { From 2006e22e40ef58af95a9938dd6e079aeb11f50b3 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 16 May 2024 17:20:41 +0700 Subject: [PATCH 24/38] Remove separate packet dispatcher channel, since "low" performance of netty dispatcher is caused by underlying socket wakeup() call (which interrupts wait() call on event loop thread), and it shouldn't be a performance issue --- .../ru/dbotthepony/mc/otm/menu/MatteryMenu.kt | 6 +- .../mc/otm/network/MatteryNetworkChannel.kt | 75 +------------------ 2 files changed, 3 insertions(+), 78 deletions(-) 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 ef2290397..1aac72633 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -387,11 +387,7 @@ abstract class MatteryMenu( val payload = synchronizerRemote.write() if (payload != null) { - if (broadcastOnce) { - MenuNetworkChannel.send(player, MenuFieldPacket(containerId, payload)) - } else { - MenuNetworkChannel.sendNow(player, MenuFieldPacket(containerId, payload)) - } + MenuNetworkChannel.send(player, MenuFieldPacket(containerId, payload)) } broadcastOnce = true 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 948084ea0..8777da206 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryNetworkChannel.kt @@ -48,12 +48,6 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) { fun sendToServer(packet: Any) = channel.send(packet, PacketDistributor.SERVER.noArg()) fun send(ply: Player, packet: Any) { - if (ply is ServerPlayer) { - queue.add(Task(channel, PacketDistributor.PLAYER.with(ply), packet)) - } - } - - fun sendNow(ply: Player, packet: Any) { if (ply is ServerPlayer) { channel.send(packet, PacketDistributor.PLAYER.with(ply)) } @@ -64,7 +58,7 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) { return } - queue.add(Task(channel, PacketDistributor.TRACKING_ENTITY.with(entity), packet)) + channel.send(packet, PacketDistributor.TRACKING_ENTITY.with(entity)) } fun sendTrackingAndSelf(entity: Entity, packet: Any) { @@ -72,14 +66,10 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) { return } - queue.add(Task(channel, PacketDistributor.TRACKING_ENTITY_AND_SELF.with(entity), packet)) + channel.send(packet, PacketDistributor.TRACKING_ENTITY_AND_SELF.with(entity)) } fun send(distributor: PacketDistributor.PacketTarget, packet: Any) { - queue.add(Task(channel, distributor, packet)) - } - - fun sendNow(distributor: PacketDistributor.PacketTarget, packet: Any) { channel.send(packet, distributor) } @@ -128,65 +118,4 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) { ) { add(packetClass.java, MatteryPacket::write, reader, MatteryPacket::play, direction, handleOnMainThread) } - - private data class Task(val channel: SimpleChannel, val target: PacketDistributor.PacketTarget, val packet: Any) - - companion object { - private val logger = LogManager.getLogger() - private var thread: Thread? = null - - private val queue = ConcurrentLinkedQueue() - - @Volatile - private var interrupt = false - - /** - * Reason behind separate thread is that Minecraft connection class does not allow to enqueue messages, - * nor does Forge. This leads to extensive calls to Netty Channel eventLoop().execute(), which is somehow resource - * heavy, as it calls wakeup on Windows, eventFdWrite on Linux, etc., when all we want to do is to enqueue packet. - * - * Concurrent safety - Minecraft Channel (send method) does not do any writes (unless player is unconnected, in which case it uses thread safe queue), hence it is thread safe. - * OTM packets are always dispatched in correct order to client. - * Netty eventLoop executor is thread safe by definition. - */ - private fun run() { - while (!interrupt) { - val task = queue.poll() - - if (task == null) { - LockSupport.park() - } else { - try { - task.channel.send(task.packet, task.target) - } catch(err: Throwable) { - logger.error("Error executing network dispatcher task", err) - } - } - } - - logger.debug("Overdrive That Matters Packet Dispatcher thread exited gracefully") - } - - internal fun onServerPostTick() { - if (queue.isNotEmpty()) { - LockSupport.unpark(thread) - } - } - - internal fun onServerStarting() { - interrupt = false - check(thread?.isAlive != true) { "Already having network dispatcher thread, ServerStartingEvent was fired twice!" } - thread = Thread(this::run, "Overdrive That Matters Network Dispatcher").also { it.isDaemon = true; it.start() } - } - - internal fun onServerStopping() { - interrupt = true - LockSupport.unpark(thread) - } - - internal fun onServerStopped() { - interrupt = true - LockSupport.unpark(thread) - } - } } From 6cc2b37b65a4761fc73f29c7049c68e9817906ee Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 16 May 2024 17:21:19 +0700 Subject: [PATCH 25/38] Bump kommons --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5024d8440..f33e9de37 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.9.15 +kommons_version=2.17.0 jei_version=16.0.0.28 jupiter_version=5.9.2 From 728a7de0bfb89dd1490585be3c4c85a5b604333b Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 16 May 2024 17:24:17 +0700 Subject: [PATCH 26/38] Update global event handler to reflect mattery network channel changes --- src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt index a8f8c9096..136e5c99f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt @@ -178,7 +178,6 @@ fun onServerTick(event: ServerTickEvent) { // чтоб не плодить кучу подписчиков, вызовем напрямую отсюда GraphNodeList.tick() AbstractProfiledStorage.onServerPostTick() - MatteryNetworkChannel.onServerPostTick() } } @@ -290,14 +289,12 @@ fun onServerStarting(event: ServerAboutToStartEvent) { _server = event.server serverThreads.add(Thread.currentThread()) serverCounter.incrementAndGet() - MatteryNetworkChannel.onServerStarting() } fun onServerStopping(event: ServerStoppingEvent) { clear() SERVER_IS_LIVE = false serverCounter.incrementAndGet() - MatteryNetworkChannel.onServerStopping() } fun onServerStopped(event: ServerStoppedEvent) { @@ -310,5 +307,4 @@ fun onServerStopped(event: ServerStoppedEvent) { _server = null serverCounter.incrementAndGet() - MatteryNetworkChannel.onServerStopped() } From 3d8e5fb774e71352fda58d7abb8335a958d8301a Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 16 May 2024 17:25:44 +0700 Subject: [PATCH 27/38] Update "nullable" usage of stream codec --- .../mc/otm/capability/MatteryPlayerCapability.kt | 5 +++-- .../kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt | 11 ++++++----- .../dbotthepony/mc/otm/menu/decorative/PainterMenu.kt | 3 ++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt index ff83d23de..52cde2994 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -69,6 +69,7 @@ import ru.dbotthepony.kommons.io.IntValueCodec import ru.dbotthepony.kommons.io.RGBCodec import ru.dbotthepony.kommons.io.UUIDValueCodec import ru.dbotthepony.kommons.io.VarIntValueCodec +import ru.dbotthepony.kommons.io.nullable import ru.dbotthepony.kommons.util.ListenableDelegate import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.kommons.util.setValue @@ -254,7 +255,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial */ var exopackGlows by publicSyncher.boolean(true) - var exopackColor by publicSyncher.add(ListenableDelegate.Box(null), RGBCodec.nullable) + var exopackColor by publicSyncher.add(ListenableDelegate.Box(null), RGBCodec.nullable()) /** * Tick event schedulers @@ -286,7 +287,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial }, backingMap = this.exopackSlotModifierMap.delegate) val regularSlotFilters = immutableList(Inventory.INVENTORY_SIZE) { - syncher.add(null, ItemValueCodec.nullable) + syncher.add(null, ItemValueCodec.nullable()) } val slotsChargeFlag = syncher.SetSlot( 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 1aac72633..8330c2c6a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -31,6 +31,7 @@ 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.io.nullable import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.kommons.util.setValue @@ -192,7 +193,7 @@ abstract class MatteryMenu( 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) - fun nullableItemInput(allowSpectators: Boolean = false, handler: (Item?) -> Unit) = PlayerInput(ItemValueCodec.nullable, allowSpectators, handler) + fun nullableItemInput(allowSpectators: Boolean = false, handler: (Item?) -> Unit) = PlayerInput(ItemValueCodec.nullable(), allowSpectators, handler) fun stringInput(allowSpectators: Boolean = false, handler: (String) -> Unit) = PlayerInput(BinaryStringCodec, allowSpectators, handler) fun floatInput(allowSpectators: Boolean = false, handler: (Float) -> Unit) = PlayerInput(FloatValueCodec, allowSpectators, handler) fun intInput(allowSpectators: Boolean = false, handler: (Int) -> Unit) = PlayerInput(VarIntValueCodec, allowSpectators, handler) @@ -441,11 +442,11 @@ abstract class MatteryMenu( val field: Delegate if (container is IMatteryContainer) { - input = PlayerInput(ItemValueCodec.nullable, handler = { container.setSlotFilter(pSlot.slotIndex, it) }) - field = mSynchronizer.add(delegate = { container.getSlotFilter(pSlot.slotIndex) }, ItemValueCodec.nullable) + input = PlayerInput(ItemValueCodec.nullable(), handler = { container.setSlotFilter(pSlot.slotIndex, it) }) + field = mSynchronizer.add(delegate = { container.getSlotFilter(pSlot.slotIndex) }, ItemValueCodec.nullable()) } else { - input = PlayerInput(ItemValueCodec.nullable, handler = { throw UnsupportedOperationException() }) - field = mSynchronizer.add(delegate = { null }, ItemValueCodec.nullable) + input = PlayerInput(ItemValueCodec.nullable(), handler = { throw UnsupportedOperationException() }) + field = mSynchronizer.add(delegate = { null }, ItemValueCodec.nullable()) } pSlot.filter = Delegate.Of(getter = field::get, setter = input::accept) 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 c72acbe93..ed6279d1a 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,6 +9,7 @@ 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.io.nullable import ru.dbotthepony.kommons.util.Listenable import ru.dbotthepony.kommons.util.ListenableDelegate import ru.dbotthepony.kommons.util.getValue @@ -46,7 +47,7 @@ class PainterMenu( val inputContainer = MatteryContainer(::rescan, 1) val outputContainer = MatteryContainer(1) private var lastRecipe: RecipeHolder? = null - var selectedRecipe by mSynchronizer.Slot(ListenableDelegate.Box(null), ResourceLocationValueCodec.nullable).also { it.addListener(Runnable { rescan() }) } + var selectedRecipe by mSynchronizer.Slot(ListenableDelegate.Box(null), ResourceLocationValueCodec.nullable()).also { it.addListener(Runnable { rescan() }) } val isBulk = BooleanInputWithFeedback(this, tile?.let { it::isBulk }) From 4e54cc7d673d7d2225ddf0c0db1a03e0116ef692 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 16 May 2024 17:27:39 +0700 Subject: [PATCH 28/38] Bump kommons --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f33e9de37..5796987d3 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.17.0 +kommons_version=2.17.2 jei_version=16.0.0.28 jupiter_version=5.9.2 From dc47b3a13e7efed405962515de005b26dbc72b77 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 16 May 2024 17:41:36 +0700 Subject: [PATCH 29/38] Replace toRGB/toARGB with toBGR/toBGRA --- .../mc/otm/capability/energy/IMatteryEnergyStorage.kt | 2 +- .../dbotthepony/mc/otm/capability/matter/IMatterStorage.kt | 2 +- .../dbotthepony/mc/otm/capability/matter/IPatternStorage.kt | 2 +- .../ru/dbotthepony/mc/otm/client/render/FontRenderer.kt | 6 +++--- .../mc/otm/compat/jade/providers/MatterBottlerProvider.kt | 2 +- .../compat/jade/providers/MatterReconstructorProvider.kt | 2 +- .../mc/otm/compat/jade/providers/MatterStorageProvider.kt | 2 +- .../mc/otm/compat/jade/providers/MatteryEnergyProvider.kt | 2 +- .../mc/otm/compat/jade/providers/MatteryWorkerProvider.kt | 4 ++-- .../ru/dbotthepony/mc/otm/item/armor/TritaniumArmorItem.kt | 2 +- .../kotlin/ru/dbotthepony/mc/otm/registry/MBlockColors.kt | 2 +- src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt | 2 +- 12 files changed, 15 insertions(+), 15 deletions(-) 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 d01d7d0fd..4dcf2b376 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 @@ -372,5 +372,5 @@ fun IMatteryEnergyStorage.getBarColor(): Int { if (!maxBatteryLevel.isPositive) return 0 - return RGBAColor.LOW_POWER.linearInterpolation((batteryLevel / maxBatteryLevel).toFloat(), RGBAColor.FULL_POWER).toRGB() + return RGBAColor.LOW_POWER.linearInterpolation((batteryLevel / maxBatteryLevel).toFloat(), RGBAColor.FULL_POWER).toBGR() } 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 34096e6b6..9ef928958 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 @@ -123,7 +123,7 @@ fun IMatterStorage.getBarWidth(): Int { } fun IMatterStorage.getBarColor(): Int { - return RGBAColor.LOW_MATTER.linearInterpolation((storedMatter / maxStoredMatter).toFloat(), RGBAColor.FULL_MATTER).toRGB() + return RGBAColor.LOW_MATTER.linearInterpolation((storedMatter / maxStoredMatter).toFloat(), RGBAColor.FULL_MATTER).toBGR() } val ICapabilityProvider.matter: IMatterStorage? get() = getCapability(MatteryCapability.MATTER).orNull() 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 0c2f26341..8b3886e1d 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 @@ -73,7 +73,7 @@ fun IPatternStorage.getBarWidth(): Int { } fun IPatternStorage.getBarColor(): Int { - return RGBAColor.LOW_PATTERNS.linearInterpolation((storedPatterns / patternCapacity).toFloat(), RGBAColor.FULL_PATTERNS).toRGB() + return RGBAColor.LOW_PATTERNS.linearInterpolation((storedPatterns / patternCapacity).toFloat(), RGBAColor.FULL_PATTERNS).toBGR() } val ICapabilityProvider.patterns: IPatternStorage? get() = getCapability(MatteryCapability.PATTERN).orNull() 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 a98bca877..0afbfc0a0 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 @@ -168,7 +168,7 @@ private fun Font.drawInternal( text, (x + shadowX) * inv, (y + shadowY) * inv, - shadowColor.toRGB(), + shadowColor.toBGR(), false, poseStack.last().pose(), buffer, @@ -192,7 +192,7 @@ private fun Font.drawInternal( text, x * inv + _x, y * inv + _y, - outlineColor.toRGB(), + outlineColor.toBGR(), drawShadow, poseStack.last().pose(), buffer, @@ -211,7 +211,7 @@ private fun Font.drawInternal( text, x * inv, y * inv, - color.toRGB(), + color.toBGR(), drawShadow, poseStack.last().pose(), buffer, 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 d43f7827f..463e215fe 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 @@ -55,7 +55,7 @@ object MatterBottlerProvider : IBlockComponentProvider, IServerDataProvider if (layer == 0) (stack.item as DyeableArmorItem).getColor(stack) else -1 }, *MItems.TRITANIUM_ARMOR.toTypedArray() ) - event.register({ _, layer -> if (layer == 1) RGBAColor.AQUA.toARGB() else -1 }, + event.register({ _, layer -> if (layer == 1) RGBAColor.AQUA.toBGRA() else -1 }, *MItems.MachineUpgrades.Creative.LIST.toTypedArray()) } From 884caba0487a9184ca8d40ef691d23c0e9ada1fa Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 16 May 2024 17:48:45 +0700 Subject: [PATCH 30/38] Use PriorityQueue over AVLTreeSet with hacks --- .../ru/dbotthepony/mc/otm/core/util/TickList.kt | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt index d3d006ba2..c6532ba4e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.core.addSorted +import java.util.PriorityQueue import java.util.concurrent.atomic.AtomicInteger class TickList : ITickable { @@ -17,8 +18,7 @@ class TickList : ITickable { private val alwaysQueued = ArrayList() private val toRemoveFromAlways = ArrayList() - private val timers = ObjectAVLTreeSet() - private val nextTimerID = AtomicInteger() + private val timers = PriorityQueue() private val namedTimers = Object2ObjectOpenHashMap(0) private var shouldTick = false @@ -32,7 +32,6 @@ class TickList : ITickable { inner class Timer(val timerTicks: Int, val runnable: Runnable) : Comparable { val ringAt = ticks + timerTicks - val timerID = nextTimerID.incrementAndGet() var finished = false private set @@ -43,10 +42,7 @@ class TickList : ITickable { } override fun compareTo(other: Timer): Int { - var c = ringAt.compareTo(other.ringAt) - if (c != 0) return c - c = timerID.compareTo(other.timerID) - return c + return ringAt.compareTo(other.ringAt) } fun execute() { @@ -230,7 +226,7 @@ class TickList : ITickable { } while (timers.isNotEmpty()) { - val head = timers.first() + val head = timers.peek() if (head.ringAt <= ticks) { head.execute() From f416cd69e54e0da0a7a9f29a3b822023483d45db Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 16 May 2024 18:06:09 +0700 Subject: [PATCH 31/38] Eliminate most of TickList's internal logic, greatly speeding it up --- .../dbotthepony/mc/otm/core/util/TickList.kt | 117 ++++-------------- 1 file changed, 27 insertions(+), 90 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt index c6532ba4e..d76dd95e1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/TickList.kt @@ -4,24 +4,16 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.core.addSorted +import java.util.LinkedList import java.util.PriorityQueue import java.util.concurrent.atomic.AtomicInteger class TickList : ITickable { - private val conditional = ArrayList() - private val conditionalQueued = ArrayList() - - private val once = ArrayList() - private val onceQueued = ArrayList() - - private val always = ArrayList() - private val alwaysQueued = ArrayList() - private val toRemoveFromAlways = ArrayList() + private val tickers = LinkedList() + private val queuedTickers = ArrayList() private val timers = PriorityQueue() - private val namedTimers = Object2ObjectOpenHashMap(0) - - private var shouldTick = false + private val namedTimers = HashMap() var inTicker = false private set @@ -37,7 +29,6 @@ class TickList : ITickable { private set init { - shouldTick = true timers.add(this) } @@ -66,9 +57,9 @@ class TickList : ITickable { return timer } - inner class Ticker(parent: ITickable) : ITickable by parent { + inner class Ticker(private val parent: ITickable) : IConditionalTickable { init { - add(this, always, alwaysQueued) + add(this) } var isEnabled = true @@ -77,19 +68,21 @@ class TickList : ITickable { field = value if (value) { - add(this, always, alwaysQueued) + add(this) } else { - alwaysQueued.remove(this) - - if (inTicker) { - toRemoveFromAlways.add(this) - } else { - always.remove(this) - } + queuedTickers.remove(this) } } } + override fun tick(): Boolean { + if (!isEnabled) + return false + + parent.tick() + return true + } + fun disable() { isEnabled = false } @@ -99,20 +92,14 @@ class TickList : ITickable { } } - private fun add(value: T, regular: MutableList, queue: MutableList) { - shouldTick = true - + fun add(value: IConditionalTickable) { if (inTicker) { - queue.add(value) + queuedTickers.add(value) } else { - regular.add(value) + tickers.add(value) } } - fun add(ticker: IConditionalTickable) { - add(ticker, conditional, conditionalQueued) - } - fun add(ticker: IConditionalTickable, condition: Boolean, reason: String) { if (!condition) { LOGGER.error("Refusing to add tickable $ticker because we $reason", IllegalStateException(reason)) @@ -123,7 +110,7 @@ class TickList : ITickable { } fun once(ticker: ITickable) { - add(ticker, once, onceQueued) + add(IConditionalTickable { ticker.tick(); false }) } fun once(ticker: ITickable, condition: Boolean, reason: String) { @@ -136,7 +123,7 @@ class TickList : ITickable { } fun always(ticker: ITickable) { - add(ticker, always, alwaysQueued) + add(IConditionalTickable { ticker.tick(); true }) } fun timer(timerTicks: Int, action: Runnable, condition: Boolean, reason: String): Timer? { @@ -170,59 +157,15 @@ class TickList : ITickable { } ticks++ - if (!shouldTick) return inTicker = true - shouldTick = timers.isNotEmpty() try { - if (conditional.isNotEmpty()) { - shouldTick = true - conditional.removeIf { !it.tick() } - } + tickers.removeIf { !it.tick() } - if (once.isNotEmpty()) { - shouldTick = true - - for (ticker in once) ticker.tick() - once.clear() - } - - if (toRemoveFromAlways.isNotEmpty()) { - shouldTick = true - - for (v in toRemoveFromAlways) always.remove(v) - toRemoveFromAlways.clear() - } - - if (always.isNotEmpty()) { - shouldTick = true - - for (ticker in always) { - ticker.tick() - } - } - - if (alwaysQueued.isNotEmpty()) { - shouldTick = true - - always.ensureCapacity(always.size + alwaysQueued.size) - for (v in alwaysQueued) always.add(v) // avoid toArray() - alwaysQueued.clear() - } - - if (conditionalQueued.isNotEmpty()) { - shouldTick = true - - for (ticker in conditionalQueued) conditional.add(ticker) - conditionalQueued.clear() - } - - if (onceQueued.isNotEmpty()) { - shouldTick = true - - for (ticker in onceQueued) once.add(ticker) - onceQueued.clear() + if (queuedTickers.isNotEmpty()) { + tickers.addAll(queuedTickers) + queuedTickers.clear() } while (timers.isNotEmpty()) { @@ -243,14 +186,8 @@ class TickList : ITickable { fun clear() { if (inTicker) throw ConcurrentModificationException() - conditional.clear() - conditionalQueued.clear() - - once.clear() - onceQueued.clear() - - always.clear() - alwaysQueued.clear() + tickers.clear() + queuedTickers.clear() timers.clear() } From 7b2d9b1bf4823eaa193bd0ee2b4459aa841491f7 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 16 May 2024 18:07:35 +0700 Subject: [PATCH 32/38] ok kotlin --- src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 8330c2c6a..1d0727448 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -782,11 +782,13 @@ abstract class MatteryMenu( val allowedTypes = EnumMap(UpgradeType::class.java) for (value in UpgradeType.ALL) { - allowedTypes[value] = mSynchronizer.boolean().delegate.also { + val b = mSynchronizer.boolean().delegate.also { if (container != null) { it.accept(value in container.allowedUpgrades) } - }::get as BooleanSupplier + } + + allowedTypes[value] = BooleanSupplier { b.get() } } val syncContainer = container ?: SimpleContainer(count) From 6af0affa4f5a228be99667e5c5afd720a9bd7104 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 16 May 2024 18:15:43 +0700 Subject: [PATCH 33/38] =?UTF-8?q?Fix=20profiled=20storage=20getting=20stuc?= =?UTF-8?q?k=20with=20last=20transfer=20numbers=20in=20history=20if=20worl?= =?UTF-8?q?d=20is=20saved=20(and=20then=20loaded)=20before=20entire=20hist?= =?UTF-8?q?ory=20is=20cleared=20with=20zeroes=20YuRaNnNzZZ=20=E2=80=94=20?= =?UTF-8?q?=D0=A1=D0=B5=D0=B3=D0=BE=D0=B4=D0=BD=D1=8F,=20=D0=B2=2018:10=20?= =?UTF-8?q?:wires:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt index f63328fb4..29aacc60d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AbstractProfiledStorage.kt @@ -126,6 +126,8 @@ abstract class AbstractProfiledStorage(val parent: P) : INBTSerializable< historyTransferInternal[i] = Decimal.deserializeNBT(it[i]) } } + + startTicking() } } From ff8d2aa5f33eecffc00d5747a1fd425085473fc3 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 31 May 2024 10:52:14 +0700 Subject: [PATCH 34/38] Bump kommons --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5796987d3..4b0741086 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.17.2 +kommons_version=3.0.1 jei_version=16.0.0.28 jupiter_version=5.9.2 From 34b60be43472c7b927d1b8ef4c6cef18ae1fed3a Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 31 May 2024 11:13:53 +0700 Subject: [PATCH 35/38] Post merge fixes for 1.20.1 --- .../ru/dbotthepony/mc/otm/network/MatteryNetworkChannel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 f4e9a1271..d28a9799b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryNetworkChannel.kt @@ -54,7 +54,7 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) { return } - channel.send(packet, PacketDistributor.TRACKING_ENTITY.with(entity)) + channel.send(PacketDistributor.TRACKING_ENTITY.with { entity }, packet) } fun sendTrackingAndSelf(entity: Entity, packet: Any) { @@ -62,7 +62,7 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) { return } - channel.send(packet, PacketDistributor.TRACKING_ENTITY_AND_SELF.with(entity)) + channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with { entity }, packet) } fun send(distributor: PacketDistributor.PacketTarget, packet: Any) { From f6138671d22ca05e5e551d7a1a199cc37235b165 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 31 May 2024 11:19:15 +0700 Subject: [PATCH 36/38] How does CAR is for 1.20.2 on 1.20.1 branch --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 29317190f..e0abdfbad 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,7 +24,7 @@ kommons_version=2.17.2 jei_version=15.2.0.27 jupiter_version=5.9.2 curios_version=5.4.7 -cosmetic_armor_reworked_id=4764779 +cosmetic_armor_reworked_id=4600191 ad_astra_id=4594155 botarium_id=4594094 resourceful_lib_id=4598948 From baeef3816f1da07a886346f7acd543f14b2fb23f Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 31 May 2024 11:33:44 +0700 Subject: [PATCH 37/38] Post merge fixes for 1.19.4 --- .../kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt | 4 ++-- .../ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt | 5 +++-- .../mc/otm/block/decorative/TritaniumPressurePlate.kt | 2 +- .../mc/otm/block/tech/BlackHoleGeneratorBlock.kt | 4 ++-- .../ru/dbotthepony/mc/otm/block/tech/HatchBlock.kt | 4 ++-- .../kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt | 9 +++++---- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt index 7bb46aece..cecd60a9f 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt @@ -30,8 +30,8 @@ fun addTags(tagsProvider: TagsProvider) { tagsProvider.plates.add("gold", MItems.GOLD_PLATE) tagsProvider.plates.add("carbon", MItems.CARBON_MESH) - tagsProvider.fluids.forge("experience").add(MFluids.LIQUID_XP).add(MFluids.LIQUID_XP_FLOWING) - tagsProvider.fluidTypes.forge("experience").add(MFluids.LIQUID_XP_TYPE) + // tagsProvider.fluids.forge("experience").add(MFluids.LIQUID_XP).add(MFluids.LIQUID_XP_FLOWING) + // tagsProvider.fluidTypes.forge("experience").add(MFluids.LIQUID_XP_TYPE) tagsProvider.items.forge("reinforced_tritanium").add(MItems.REINFORCED_TRITANIUM_PLATE) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt index 41ad89edd..eb13298c7 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt @@ -167,8 +167,9 @@ class TagsProvider(private val event: GatherDataEvent) { val blocks = Delegate(ForgeRegistries.BLOCKS) val items = Delegate(ForgeRegistries.ITEMS) - val fluids = Delegate(ForgeRegistries.FLUIDS) - val fluidTypes = Delegate(ForgeRegistries.Keys.FLUID_TYPES) + // not supported on 1.19.4 and earlier + // val fluids = Delegate(ForgeRegistries.FLUIDS) + // val fluidTypes = Delegate(ForgeRegistries.Keys.FLUID_TYPES) val mobEffects = Delegate(ForgeRegistries.MOB_EFFECTS) val damageTypes = Delegate(Registries.DAMAGE_TYPE) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt index effe87a68..45d63f188 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt @@ -23,7 +23,7 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.collect.iteratorOf import ru.dbotthepony.mc.otm.core.get -class TritaniumPressurePlate(color: DyeColor?) : BasePressurePlateBlock(Properties.of(Material.METAL, color ?: DyeColor.LIGHT_BLUE).sound(SoundType.METAL).explosionResistance(80f).noOcclusion().destroyTime(3f).requiresCorrectToolForDrops().forceSolidOn().noCollission(), BlockSetType.IRON) { +class TritaniumPressurePlate(color: DyeColor?) : BasePressurePlateBlock(Properties.of(Material.METAL, color ?: DyeColor.LIGHT_BLUE).sound(SoundType.METAL).explosionResistance(80f).noOcclusion().destroyTime(3f).requiresCorrectToolForDrops().noCollission(), BlockSetType.IRON) { val tooltips = TooltipList() override fun appendHoverText( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BlackHoleGeneratorBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BlackHoleGeneratorBlock.kt index fc722dfe9..e0b445a89 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BlackHoleGeneratorBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BlackHoleGeneratorBlock.kt @@ -9,7 +9,7 @@ import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.entity.BlockEntityTicker import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.BlockState -import net.minecraft.world.level.material.MapColor +import net.minecraft.world.level.material.Material import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.BlackHoleGeneratorBlockEntity @@ -17,7 +17,7 @@ import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom import ru.dbotthepony.mc.otm.core.math.plus import ru.dbotthepony.mc.otm.core.math.times -class BlackHoleGeneratorBlock : RotatableMatteryBlock(Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)), EntityBlock { +class BlackHoleGeneratorBlock : RotatableMatteryBlock(Properties.of(Material.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)), EntityBlock { override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity { return BlackHoleGeneratorBlockEntity(blockPos, blockState) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/HatchBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/HatchBlock.kt index 6a9871af4..1b750b262 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/HatchBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/HatchBlock.kt @@ -9,12 +9,12 @@ import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.entity.BlockEntityTicker import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.BlockState -import net.minecraft.world.level.material.MapColor +import net.minecraft.world.level.material.Material import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.core.TranslatableComponent -class HatchBlock(val factory: BlockEntityType.BlockEntitySupplier, val needsTicking: Boolean = false) : RotatableMatteryBlock(Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(80.0f)), EntityBlock { +class HatchBlock(val factory: BlockEntityType.BlockEntitySupplier, val needsTicking: Boolean = false) : RotatableMatteryBlock(Properties.of(Material.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(80.0f)), EntityBlock { override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity { return factory.create(blockPos, blockState) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt index 781fe692f..36cd4a319 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MBlocks.kt @@ -1,6 +1,7 @@ package ru.dbotthepony.mc.otm.registry import net.minecraft.util.valueproviders.UniformInt +import net.minecraft.world.item.DyeColor import net.minecraft.world.level.block.AnvilBlock import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.DropExperienceBlock @@ -139,11 +140,11 @@ object MBlocks { val FLUID_TANK: FluidTankBlock by registry.register(MNames.FLUID_TANK) { FluidTankBlock() } val DEV_CHEST: DevChestBlock by registry.register(MNames.DEV_CHEST) { DevChestBlock() } - val MULTIBLOCK_STRUCTURE by registry.register(MNames.MULTIBLOCK_STRUCTURE) { MatteryBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } + val MULTIBLOCK_STRUCTURE by registry.register(MNames.MULTIBLOCK_STRUCTURE) { MatteryBlock(BlockBehaviour.Properties.of(Material.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } val BLACK_HOLE_GENERATOR by registry.register(MNames.BLACK_HOLE_GENERATOR) { BlackHoleGeneratorBlock() } - val MATTER_INJECTOR by registry.register(MNames.MATTER_INJECTOR) { RotatableMatteryBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } - val ANTIMATTER_INJECTOR by registry.register(MNames.ANTIMATTER_INJECTOR) { RotatableMatteryBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } - val HIGH_ENERGY_PARTICLE_COLLECTOR by registry.register(MNames.HIGH_ENERGY_PARTICLE_COLLECTOR) { RotatableMatteryBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } + val MATTER_INJECTOR by registry.register(MNames.MATTER_INJECTOR) { RotatableMatteryBlock(BlockBehaviour.Properties.of(Material.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } + val ANTIMATTER_INJECTOR by registry.register(MNames.ANTIMATTER_INJECTOR) { RotatableMatteryBlock(BlockBehaviour.Properties.of(Material.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } + val HIGH_ENERGY_PARTICLE_COLLECTOR by registry.register(MNames.HIGH_ENERGY_PARTICLE_COLLECTOR) { RotatableMatteryBlock(BlockBehaviour.Properties.of(Material.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)) } val ITEM_INPUT_HATCH by registry.register(MNames.ITEM_INPUT_HATCH) { HatchBlock(ItemHatchBlockEntity::input) } val ITEM_OUTPUT_HATCH by registry.register(MNames.ITEM_OUTPUT_HATCH) { HatchBlock(ItemHatchBlockEntity::output) } val ENERGY_INPUT_HATCH by registry.register(MNames.ENERGY_INPUT_HATCH) { HatchBlock(EnergyHatchBlockEntity::input) } From eeb5d3ba73852da369e510724690721ae7736061 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 31 May 2024 12:21:29 +0700 Subject: [PATCH 38/38] Post merge fixes for 1.19.3 --- .../mc/otm/android/feature/EnderTeleporterFeature.kt | 2 -- .../otm/block/decorative/TritaniumPressurePlate.kt | 2 +- .../kotlin/ru/dbotthepony/mc/otm/registry/MMenus.kt | 12 ++++++------ 3 files changed, 7 insertions(+), 9 deletions(-) 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 3c66fafbd..d5b0f9ce6 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 @@ -38,8 +38,6 @@ import ru.dbotthepony.mc.otm.client.render.sprites.sprite 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/block/decorative/TritaniumPressurePlate.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt index 09f5f2bf9..518f105f9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/decorative/TritaniumPressurePlate.kt @@ -25,7 +25,7 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.collect.iteratorOf import ru.dbotthepony.mc.otm.core.get -class TritaniumPressurePlate(color: DyeColor?) : BasePressurePlateBlock(Properties.of(Material.METAL, color ?: DyeColor.LIGHT_BLUE).sound(SoundType.METAL).explosionResistance(80f).noOcclusion().destroyTime(3f).requiresCorrectToolForDrops().noCollission(), BlockSetType.IRON) { +class TritaniumPressurePlate(color: DyeColor?) : BasePressurePlateBlock(Properties.of(Material.METAL, color ?: DyeColor.LIGHT_BLUE).sound(SoundType.METAL).explosionResistance(80f).noOcclusion().destroyTime(3f).requiresCorrectToolForDrops().noCollission()) { val tooltips = TooltipList() override fun appendHoverText( itemStack: ItemStack, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MMenus.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MMenus.kt index 1b537140c..de8d1f19c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MMenus.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MMenus.kt @@ -109,12 +109,12 @@ object MMenus { val FLUID_TANK by registry.register(MNames.FLUID_TANK) { MenuType(::FluidTankMenu) } val PAINTER by registry.register(MNames.PAINTER) { MenuType(::PainterMenu) } val MATTER_ENTANGLER by registry.register(MNames.MATTER_ENTANGLER) { MenuType(::MatterEntanglerMenu) } - val ITEM_INPUT_HATCH by registry.register(MNames.ITEM_INPUT_HATCH) { MenuType(ItemHatchMenu::input, FeatureFlags.VANILLA_SET) } - val ITEM_OUTPUT_HATCH by registry.register(MNames.ITEM_OUTPUT_HATCH) { MenuType(ItemHatchMenu::output, FeatureFlags.VANILLA_SET) } - val MATTER_INPUT_HATCH by registry.register(MNames.MATTER_INPUT_HATCH) { MenuType(MatterHatchMenu::input, FeatureFlags.VANILLA_SET) } - val MATTER_OUTPUT_HATCH by registry.register(MNames.MATTER_OUTPUT_HATCH) { MenuType(MatterHatchMenu::output, FeatureFlags.VANILLA_SET) } - val ENERGY_INPUT_HATCH by registry.register(MNames.ENERGY_INPUT_HATCH) { MenuType(EnergyHatchMenu::input, FeatureFlags.VANILLA_SET) } - val ENERGY_OUTPUT_HATCH by registry.register(MNames.ENERGY_OUTPUT_HATCH) { MenuType(EnergyHatchMenu::output, FeatureFlags.VANILLA_SET) } + val ITEM_INPUT_HATCH by registry.register(MNames.ITEM_INPUT_HATCH) { MenuType(ItemHatchMenu::input) } + val ITEM_OUTPUT_HATCH by registry.register(MNames.ITEM_OUTPUT_HATCH) { MenuType(ItemHatchMenu::output) } + val MATTER_INPUT_HATCH by registry.register(MNames.MATTER_INPUT_HATCH) { MenuType(MatterHatchMenu::input) } + val MATTER_OUTPUT_HATCH by registry.register(MNames.MATTER_OUTPUT_HATCH) { MenuType(MatterHatchMenu::output) } + val ENERGY_INPUT_HATCH by registry.register(MNames.ENERGY_INPUT_HATCH) { MenuType(EnergyHatchMenu::input) } + val ENERGY_OUTPUT_HATCH by registry.register(MNames.ENERGY_OUTPUT_HATCH) { MenuType(EnergyHatchMenu::output) } val STORAGE_BUS by registry.register(MNames.STORAGE_BUS) { MenuType(::StorageBusMenu) } val STORAGE_IMPORTER_EXPORTER by registry.register(MNames.STORAGE_IMPORTER) { MenuType(::StorageImporterExporterMenu) }