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 e9002aed7..10e63ae72 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt @@ -14,7 +14,7 @@ import net.minecraftforge.fml.common.Mod import net.minecraftforge.data.event.GatherDataEvent import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.block.* -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock import ru.dbotthepony.mc.otm.block.matter.PatternStorageBlock import ru.dbotthepony.mc.otm.block.storage.DriveViewerBlock @@ -30,7 +30,7 @@ import ru.dbotthepony.mc.otm.datagen.models.BlockMatteryModelProvider import ru.dbotthepony.mc.otm.datagen.recipes.MatteryRecipeProvider import ru.dbotthepony.mc.otm.datagen.recipes.has import ru.dbotthepony.mc.otm.registry.* -import ru.dbotthepony.mc.otm.* +import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider import ru.dbotthepony.mc.otm.datagen.loot.addLootModifiers import ru.dbotthepony.mc.otm.datagen.recipes.addCraftingTableRecipes diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/MatteryBlockStateProvider.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/MatteryBlockStateProvider.kt index add36a39e..4857cc46b 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/MatteryBlockStateProvider.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/blocks/MatteryBlockStateProvider.kt @@ -7,12 +7,12 @@ import net.minecraftforge.client.model.generators.BlockStateProvider import net.minecraftforge.client.model.generators.ConfiguredModel import net.minecraftforge.data.event.GatherDataEvent import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.getValueNullable import ru.dbotthepony.mc.otm.datagen.toXRotBlockstate import ru.dbotthepony.mc.otm.datagen.toYRotBlockstate -import ru.dbotthepony.mc.otm.registryName +import ru.dbotthepony.mc.otm.core.registryName typealias AdvancedBlockStateFunction = (BlockState, ConfiguredModel.Builder<*>, String) -> String? private data class AdvancedBlockStateEntry(val block: Block, val func: AdvancedBlockStateFunction) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/MatteryItemModelProvider.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/MatteryItemModelProvider.kt index 5962da99c..88fc2ec00 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/MatteryItemModelProvider.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/items/MatteryItemModelProvider.kt @@ -6,7 +6,7 @@ import net.minecraftforge.client.model.generators.ItemModelProvider import net.minecraftforge.data.event.GatherDataEvent import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.datagen.DataGen -import ru.dbotthepony.mc.otm.registryName +import ru.dbotthepony.mc.otm.core.registryName private data class SimpleItemModel(val item: String, val path: ResourceLocation) { val traceback = IllegalArgumentException("Failed to register model") 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 ec110f063..349bbdbf5 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 @@ -53,6 +53,10 @@ private fun misc(provider: MatteryLanguageProvider) { gui("exosuit.already_activated", "You already have exosuit following you") + gui("power_supplier.active_nodes", "Currently demanding nodes: %s") + + misc("battery.single_use", "Single use battery, can not be recharged.") + misc("exosuit.granted1", "As you keep pressing fingerprint reader, you are getting hurt in finger.") misc("exosuit.granted2", "After you raise your finger, fingerprint reader glows very bright.") misc("exosuit.granted3", "Then, fingerprint reader fades, leaving faint trace not of your finger, but of your very soul.") @@ -128,6 +132,9 @@ private fun misc(provider: MatteryLanguageProvider) { misc("item.power.normal.storage", "Stored energy: %s / %s") misc("item.power.normal.throughput", "Max I/O %s / %s") + misc("item.power.output_only", "Max output %s") + misc("item.power.input_only", "Max input %s") + misc("item.pattern.stored", "Stored patterns: %s / %s") misc("item.pattern.infinite.stored", "Stored patterns %s") misc("item.pattern.line", "%s [%s%%]") @@ -377,6 +384,9 @@ private fun items(provider: MatteryLanguageProvider) { add(MItems.TRITANIUM_ORE_CLUMP, "Raw Tritanium") add(MItems.PATTERN_DRIVE_NORMAL, "Pattern Drive") add(MItems.PATTERN_DRIVE_CREATIVE, "Creative Pattern Drive") + + add(MItems.ZPM_BATTERY, "Zero Point Module") + add(MItems.ZPM_BATTERY, "description", "Can be found in hands of those who travel between dimensions, if they ever reached different reality of origin of these constructs...") } } diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt index 5e7bf7912..eb9bfb77e 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt @@ -39,11 +39,12 @@ fun addLootModifiers(it: LootModifiers) { ItemStack(MItems.PILL_ANDROID, 1) to 0.5 )) - it.add("end_city_pill", LootTableBasicAppender( + it.add("end_city_modifications", LootTableBasicAppender( arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/end_city_treasure")).build()), ItemStack(MItems.PILL_ANDROID, 1) to 0.1, ItemStack(MItems.PILL_HUMANE, 1) to 0.3, ItemStack(MItems.PILL_OBLIVION, 1) to 0.5, + ItemStack(MItems.ZPM_BATTERY, 1) to 0.005, )) it.add("shipwreck_supply_pill", LootTableBasicAppender( diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelBuilder.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelBuilder.kt index f61057840..b5eda7286 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelBuilder.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelBuilder.kt @@ -9,7 +9,8 @@ import net.minecraft.core.Direction import net.minecraft.resources.ResourceLocation import net.minecraftforge.client.model.generators.ModelBuilder import net.minecraftforge.common.data.ExistingFileHelper -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set data class TextureSize(val width: Float, val height: Float) { constructor(arr: JsonArray) : this(arr[0].asFloat, arr[1].asFloat) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelProvider.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelProvider.kt index cf68574cb..c87fc106d 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelProvider.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/models/MatteryModelProvider.kt @@ -8,7 +8,7 @@ import net.minecraft.world.level.block.Block import net.minecraftforge.client.model.generators.ModelProvider import net.minecraftforge.data.event.GatherDataEvent import ru.dbotthepony.mc.otm.datagen.DataGen -import ru.dbotthepony.mc.otm.registryName +import ru.dbotthepony.mc.otm.core.registryName private typealias Callback = (MatteryModelProvider) -> Unit diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt index 36d922695..f1b60c234 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/CraftingTableRecipes.kt @@ -4,8 +4,6 @@ import net.minecraft.data.recipes.FinishedRecipe import net.minecraft.data.recipes.ShapedRecipeBuilder import net.minecraft.data.recipes.ShapelessRecipeBuilder import net.minecraft.resources.ResourceLocation -import net.minecraft.tags.TagKey -import net.minecraft.world.item.Item import net.minecraft.world.item.Items import net.minecraft.world.item.crafting.Ingredient import net.minecraftforge.common.Tags @@ -15,7 +13,7 @@ import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MRegistry -import ru.dbotthepony.mc.otm.registryName +import ru.dbotthepony.mc.otm.core.registryName import java.util.function.Consumer fun addCraftingTableRecipes(consumer: Consumer) { @@ -55,6 +53,22 @@ fun addCraftingTableRecipes(consumer: Consumer) { .build(consumer) } + MatteryRecipe(MBlocks.PLATE_PRESS) + .row(MItems.ELECTRIC_PARTS, MItems.ENERGY_BUS, MItems.ELECTRIC_PARTS) + .row(MItemTags.INGOT_TRITANIUM, Items.BLAST_FURNACE, MItemTags.INGOT_TRITANIUM) + .row(MItemTags.PISTONS, MItemTags.INGOT_TRITANIUM, MItemTags.PISTONS) + .unlockedBy(MItemTags.INGOT_TRITANIUM) + .unlockedBy(MItems.ELECTRIC_PARTS) + .build(consumer) + + MatteryRecipe(MBlocks.PLATE_PRESS) + .rowB(MItemTags.BASIC_CIRCUIT) + .row(MItemTags.PLATE_TRITANIUM, MItems.MACHINE_FRAME, MItemTags.PLATE_TRITANIUM) + .rowAC(MItemTags.PISTONS, MItemTags.PISTONS) + .unlockedBy(MItemTags.INGOT_TRITANIUM) + .unlockedBy(MItems.ELECTRIC_PARTS) + .build(consumer, "advanced") + MatteryRecipe(MBlocks.TRITANIUM_STRIPED_BLOCK, 24) .rowB(MItemTags.PLATE_TRITANIUM) .row(MItemTags.PLATE_TRITANIUM, COBBLESTONE, MItemTags.PLATE_TRITANIUM) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/MatteryRecipe.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/MatteryRecipe.kt index bf112878b..898f2760b 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/MatteryRecipe.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/MatteryRecipe.kt @@ -11,7 +11,7 @@ import net.minecraft.world.item.Item import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.level.ItemLike import ru.dbotthepony.mc.otm.OverdriveThatMatters -import ru.dbotthepony.mc.otm.registryName +import ru.dbotthepony.mc.otm.core.registryName import java.util.function.Consumer private interface RecipeCell { diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/PlatePressFinishedRecipe.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/PlatePressFinishedRecipe.kt index d6b85c78f..948b8ac53 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/PlatePressFinishedRecipe.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/recipes/PlatePressFinishedRecipe.kt @@ -7,7 +7,8 @@ import net.minecraft.resources.ResourceLocation import net.minecraft.world.item.crafting.RecipeSerializer import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe import ru.dbotthepony.mc.otm.recipe.PlatePressRecipeFactory -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set class PlatePressFinishedRecipe(private val recipe: PlatePressRecipe) : FinishedRecipe { override fun serializeRecipeData(it: JsonObject) { diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index ab93ceed1..8be14da45 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -2,8 +2,10 @@ package ru.dbotthepony.mc.otm; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.fml.ModList; @@ -15,15 +17,15 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue; import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; import ru.dbotthepony.mc.otm.capability.drive.DrivePool; +import ru.dbotthepony.mc.otm.client.ClientEventHandler; import ru.dbotthepony.mc.otm.client.MatteryGUI; -import ru.dbotthepony.mc.otm.client.EventHandlerKt; import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel; import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel; import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt; import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt; import ru.dbotthepony.mc.otm.core.ImpreciseFraction; +import ru.dbotthepony.mc.otm.item.QuantumBatteryItem; import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem; import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem; import ru.dbotthepony.mc.otm.matter.MatterDataKt; @@ -33,6 +35,8 @@ import ru.dbotthepony.mc.otm.registry.*; import ru.dbotthepony.mc.otm.storage.*; import ru.dbotthepony.mc.otm.worldgen.OreGen; +import static net.minecraftforge.common.MinecraftForge.EVENT_BUS; + import javax.annotation.ParametersAreNonnullByDefault; // The value here should match an entry in the META-INF/mods.toml file @@ -76,49 +80,78 @@ public final class OverdriveThatMatters { INSTANCE = this; - MRegistry.INSTANCE.initialize(FMLJavaModLoadingContext.get()); + var modBus = FMLJavaModLoadingContext.get().getModEventBus(); - FMLJavaModLoadingContext.get().getModEventBus().addListener(EventPriority.HIGHEST, this::setup); - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setupClient); + MRegistry.INSTANCE.initialize(modBus); - MinecraftForge.EVENT_BUS.register(this); - MinecraftForge.EVENT_BUS.register(GlobalEventHandlerKt.class); - MinecraftForge.EVENT_BUS.register(MatteryPlayerCapability.Companion); - MinecraftForge.EVENT_BUS.register(MatterRegistryKt.class); - MinecraftForge.EVENT_BUS.register(MatterDataKt.class); - MinecraftForge.EVENT_BUS.register(ExplosionQueue.Companion); - MinecraftForge.EVENT_BUS.register(AbstractWeaponItem.Companion); - - FMLJavaModLoadingContext.get().getModEventBus().register(MatteryCapability.class); - - FMLJavaModLoadingContext.get().getModEventBus().register(MRecipes.class); - - MinecraftForge.EVENT_BUS.register(DrivePool.INSTANCE); - MinecraftForge.EVENT_BUS.register(PortableCondensationDriveItem.Companion); - - FMLJavaModLoadingContext.get().getModEventBus().addListener(MatteryPlayerCapability::registerEffects); + modBus.addListener(EventPriority.HIGHEST, this::setup); + modBus.addListener(EventPriority.NORMAL, this::setupClient); } private void setup(final FMLCommonSetupEvent event) { + EVENT_BUS.addListener(EventPriority.LOWEST, DrivePool.INSTANCE::onServerPostTick); + EVENT_BUS.addListener(EventPriority.HIGHEST, DrivePool.INSTANCE::serverStopEvent); + EVENT_BUS.addListener(EventPriority.HIGHEST, DrivePool.INSTANCE::serverStartEvent); + EVENT_BUS.addListener(EventPriority.NORMAL, DrivePool.INSTANCE::onWorldSave); + + EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopped); + EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopping); + EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStarting); + EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onWorldTick); + EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onServerTick); + + EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onLivingTick); + EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onHurtEvent); + EVENT_BUS.addGenericListener(Entity.class, EventPriority.NORMAL, MatteryPlayerCapability.Companion::onAttachCapabilityEvent); + EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerChangeDimensionEvent); + EVENT_BUS.addListener(EventPriority.LOWEST, MatteryPlayerCapability.Companion::onPlayerDeath); + EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerCloneEvent); + EVENT_BUS.addListener(EventPriority.LOW, MatteryPlayerCapability.Companion::onPickupEvent); + + EVENT_BUS.addListener(EventPriority.LOW, MatterDataKt::serverStartData); + EVENT_BUS.addListener(EventPriority.NORMAL, MatterRegistryKt::onPlayerJoin); + EVENT_BUS.addListener(EventPriority.NORMAL, ExplosionQueue.Companion::onWorldTick); + EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::tick); + EVENT_BUS.addListener(EventPriority.NORMAL, QuantumBatteryItem.Companion::tick); + EVENT_BUS.addListener(EventPriority.LOWEST, PortableCondensationDriveItem.Companion::onPickupEvent); + + MatteryPlayerCapability.Companion.registerEffects(event); + MatteryPlayerNetworkChannel.INSTANCE.register(); MenuNetworkChannel.INSTANCE.register(); WeaponNetworkChannel.INSTANCE.register(); RegistryNetworkChannel.INSTANCE.register(); WorldNetworkChannel.INSTANCE.register(); + GenericNetworkChannel.INSTANCE.register(); ITEM_STORAGE = StorageRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new ImpreciseFraction("3.125")); if (ModList.get().isLoaded("mekanism")) { - MinecraftForge.EVENT_BUS.register(QIOKt.class); - MinecraftForge.EVENT_BUS.register(TooltipsKt.class); + EVENT_BUS.addGenericListener(BlockEntity.class, EventPriority.NORMAL, QIOKt::attachCapabilities); } OreGen.INSTANCE.register(); } private void setupClient(final FMLClientSetupEvent event) { - MinecraftForge.EVENT_BUS.register(MatteryGUI.INSTANCE); - MinecraftForge.EVENT_BUS.register(EventHandlerKt.class); + EVENT_BUS.addListener(EventPriority.NORMAL, MatterRegistryKt::tooltipEvent); + + EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::playerRenderHook); + EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::fovHook); + EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::clickHook); + EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::renderViewModel); + + EVENT_BUS.addListener(EventPriority.NORMAL, MatteryGUI.INSTANCE::onScreenRender); + EVENT_BUS.addListener(EventPriority.LOWEST, MatteryGUI.INSTANCE::onOpenGUIEvent); + EVENT_BUS.addListener(EventPriority.NORMAL, MatteryGUI.INSTANCE::onRenderGuiEvent); + EVENT_BUS.addListener(EventPriority.HIGH, MatteryGUI.INSTANCE::onLayerRenderEvent); + + EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandler.INSTANCE::inputEvent); + EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandler.INSTANCE::screenOpen); + + if (ModList.get().isLoaded("mekanism")) { + EVENT_BUS.addListener(EventPriority.NORMAL, TooltipsKt::tooltipEvent); + } event.enqueueWork(GlobalEventHandlerKt::recordClientThread); diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java index 461330c6b..0d0741da5 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java @@ -5,7 +5,7 @@ import net.minecraftforge.common.capabilities.*; import org.jetbrains.annotations.NotNull; import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive; import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; -import ru.dbotthepony.mc.otm.capability.matter.IMatterTaskProvider; +import ru.dbotthepony.mc.otm.capability.matter.IReplicationTaskProvider; import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage; import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode; import ru.dbotthepony.mc.otm.graph.storage.IStorageGraphNode; @@ -36,7 +36,7 @@ public class MatteryCapability { @Nonnull @NotNull - public static final Capability TASK = CapabilityManager.get(new CapabilityToken<>() {}); + public static final Capability TASK = CapabilityManager.get(new CapabilityToken<>() {}); @Nonnull @NotNull @@ -49,16 +49,4 @@ public class MatteryCapability { @Nonnull @NotNull public static final Capability MEKANISM_ENERGY = CapabilityManager.get(new CapabilityToken<>() {}); - - @SuppressWarnings("unused") - public static void register(final RegisterCapabilitiesEvent event) { - event.register(IMatteryEnergyStorage.class); - event.register(MatteryPlayerCapability.class); - event.register(IMatterHandler.class); - event.register(IPatternStorage.class); - event.register(IMatterTaskProvider.class); - event.register(IMatteryDrive.class); - event.register(IStorageGraphNode.class); - event.register(IMatterGraphNode.class); - } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/matter/MatterTask.java b/src/main/java/ru/dbotthepony/mc/otm/capability/matter/MatterTask.java deleted file mode 100644 index 75f4b0f14..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/matter/MatterTask.java +++ /dev/null @@ -1,147 +0,0 @@ -package ru.dbotthepony.mc.otm.capability.matter; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.ForgeRegistry; -import net.minecraftforge.registries.RegistryManager; -import ru.dbotthepony.mc.otm.UnOverengineeringKt; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.Objects; -import java.util.UUID; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public record MatterTask(UUID id, @Nullable UUID pattern, Item item, int in_progress, int finished, int required) { - public MatterTask(UUID id, @Nullable UUID pattern, Item item, int in_progress, int finished, int required) { - this.id = id; - this.pattern = pattern; - this.item = item; - this.in_progress = Math.max(0, in_progress); - this.finished = Math.max(0, finished); - this.required = Math.max(0, required); - } - - @Override - public int hashCode() { - return id.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof MatterTask obj1) - return obj1.id.equals(id); - - return false; - } - - public ItemStack stack() { - return new ItemStack(item, 1); - } - - public ItemStack stack(int amount) { - return new ItemStack(item, amount); - } - - public int total() { - return in_progress + finished + required; - } - - public MatterTask shrinkRequired(int amount) { - return new MatterTask(id, pattern, item, in_progress + amount, finished, required - amount); - } - - public MatterTask shrinkInProgress(int amount) { - return new MatterTask(id, pattern, item, in_progress - amount, finished + amount, required); - } - - public CompoundTag serializeNBT() { - CompoundTag tag = new CompoundTag(); - - tag.putLong("id_l", id.getLeastSignificantBits()); - tag.putLong("id_u", id.getMostSignificantBits()); - - if (pattern != null) { - tag.putLong("pattern_l", pattern.getLeastSignificantBits()); - tag.putLong("pattern_u", pattern.getMostSignificantBits()); - } - - tag.putString("item", Objects.requireNonNull(UnOverengineeringKt.getRegistryName(item)).toString()); - tag.putInt("in_progress", in_progress); - tag.putInt("finished", finished); - tag.putInt("required", required); - - return tag; - } - - @Nullable - public static MatterTask deserializeNBT(@Nullable Tag nbt) { - if (nbt == null) - return null; - - if (nbt instanceof CompoundTag tag) { - Item get_item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(tag.getString("item"))); - - if (get_item != null && get_item != Items.AIR) { - long a = tag.getLong("pattern_u"); - long b = tag.getLong("pattern_l"); - - UUID pattern = a != 0 && b != 0 ? new UUID(a, b) : null; - - return new MatterTask( - new UUID(tag.getLong("id_u"), tag.getLong("id_l")), - pattern, - get_item, - tag.getInt("in_progress"), - tag.getInt("finished"), - tag.getInt("required") - ); - } - } - - return null; - } - - public void write(FriendlyByteBuf buffer) { - buffer.writeLong(id.getMostSignificantBits()); - buffer.writeLong(id.getLeastSignificantBits()); - - if (pattern != null) { - buffer.writeBoolean(true); - - buffer.writeLong(pattern.getMostSignificantBits()); - buffer.writeLong(pattern.getLeastSignificantBits()); - } else { - buffer.writeBoolean(false); - } - - buffer.writeInt(((ForgeRegistry) ForgeRegistries.ITEMS).getID(item)); - buffer.writeInt(in_progress); - buffer.writeInt(finished); - buffer.writeInt(required); - } - - @Nullable - public static MatterTask read(FriendlyByteBuf buffer) { - var id = new UUID(buffer.readLong(), buffer.readLong()); - var pattern = buffer.readBoolean() ? new UUID(buffer.readLong(), buffer.readLong()) : null; - var item = ((ForgeRegistry) ForgeRegistries.ITEMS).getValue(buffer.readInt()); - - if (item == null) - return null; - - var in_progress = buffer.readInt(); - var finished = buffer.readInt(); - var required = buffer.readInt(); - - return new MatterTask(id, pattern, item, in_progress, finished, required); - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/matter/PatternState.java b/src/main/java/ru/dbotthepony/mc/otm/capability/matter/PatternState.java deleted file mode 100644 index 7cdf85a33..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/matter/PatternState.java +++ /dev/null @@ -1,95 +0,0 @@ -package ru.dbotthepony.mc.otm.capability.matter; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.ForgeRegistry; -import net.minecraftforge.registries.RegistryManager; -import ru.dbotthepony.mc.otm.UnOverengineeringKt; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Objects; -import java.util.UUID; - -public record PatternState(@Nonnull UUID id, @Nonnull Item item, double research) { - public PatternState(@Nonnull UUID id, @Nonnull Item item, double research) { - this.id = id; - this.item = item; - this.research = Math.max(0, Math.min(1, research)); - } - - @Override - public boolean equals(Object state) { - if (state instanceof PatternState state1) - return state1.id.equals(id); - - return false; - } - - public ItemStack stack() { - return new ItemStack(item, 1); - } - - @Override - public int hashCode() { - return id.hashCode(); - } - - public CompoundTag serializeNBT() { - var tag = new CompoundTag(); - - tag.putLong("id_m", id.getMostSignificantBits()); - tag.putLong("id_l", id.getLeastSignificantBits()); - tag.putString("item", Objects.requireNonNull(UnOverengineeringKt.getRegistryName(item)).toString()); - tag.putDouble("research_percent", research); - - return tag; - } - - @Nullable - public static PatternState deserializeNBT(Tag nbt) { - if (nbt instanceof CompoundTag tag) { - var item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(tag.getString("item"))); - - if (item == null) - return null; - - var id = new UUID(tag.getLong("id_m"), tag.getLong("id_l")); - var research_percent = tag.getDouble("research_percent"); - - return new PatternState(id, item, research_percent); - } - - return null; - } - - public void write(FriendlyByteBuf buffer) { - buffer.writeLong(id.getMostSignificantBits()); - buffer.writeLong(id.getLeastSignificantBits()); - - buffer.writeInt(((ForgeRegistry) ForgeRegistries.ITEMS).getID(item)); - - buffer.writeDouble(research); - } - - @Nullable - public static PatternState read(FriendlyByteBuf buffer) { - long ida = buffer.readLong(); - long idb = buffer.readLong(); - - int item = buffer.readInt(); - double percent = buffer.readDouble(); - - Item get_item = ((ForgeRegistry) ForgeRegistries.ITEMS).getValue(item); - - if (get_item == null) - return null; - - return new PatternState(new UUID(ida, idb), get_item, percent); - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/client/screen/MatterPanelScreen.java b/src/main/java/ru/dbotthepony/mc/otm/client/screen/MatterPanelScreen.java deleted file mode 100644 index 5ac14491d..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/client/screen/MatterPanelScreen.java +++ /dev/null @@ -1,401 +0,0 @@ -package ru.dbotthepony.mc.otm.client.screen; - -import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.components.EditBox; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ItemStack; -import ru.dbotthepony.mc.otm.capability.matter.MatterTask; -import ru.dbotthepony.mc.otm.capability.matter.PatternState; -import ru.dbotthepony.mc.otm.menu.MatterPanelMenu; -import ru.dbotthepony.mc.otm.menu.ReplicationRequestPacket; -import ru.dbotthepony.mc.otm.network.MenuNetworkChannel; -import ru.dbotthepony.mc.otm.client.screen.panels.*; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; - -import static ru.dbotthepony.mc.otm.UnOverengineeringKt.TextComponent; -import static ru.dbotthepony.mc.otm.UnOverengineeringKt.TranslatableComponent; - -public class MatterPanelScreen extends MatteryScreen { - private static final int MODAL_WIDTH = 213; - private static final int MODAL_HEIGHT = 110; - - public MatterPanelScreen(MatterPanelMenu p_97741_, Inventory p_97742_, Component p_97743_) { - super(p_97741_, p_97742_, p_97743_); - - imageWidth = 176; - imageHeight = 187; - - titleLabelY = 5; - } - - public static final int GRID_WIDTH = 8; - public static final int GRID_HEIGHT = 9; - - private final ArrayList pattern_slots = new ArrayList<>(); - private final ArrayList task_slots = new ArrayList<>(); - - @Nullable - @Override - protected FramePanel makeMainFrame() { - float width = GRID_WIDTH * AbstractSlotPanel.SIZE + ScrollBarConstants.WIDTH + FramePanel.PADDING * 2 + 8; - float height = GRID_HEIGHT * AbstractSlotPanel.SIZE + FramePanel.PADDING_TOP + FramePanel.PADDING; - - var scroll_panel = new ContinuousScrollBarPanel(this, null, 0, 0, 0); - - var frame = new FramePanel(this, null, 0, 0, width, height, getTitle()) { - @Override - protected boolean mouseScrolledInner(double x, double y, double scroll) { - return scroll_panel.mouseScrolledInner(x, y, scroll); - } - }; - - var patterns_tab = frame.addTab(FramePanel.Position.TOP, () -> { - for (var slot : pattern_slots) { - slot.setVisible(true); - } - }, () -> { - for (var slot : pattern_slots) { - slot.setVisible(false); - } - }); - - var tasks_tab = frame.addTab(FramePanel.Position.TOP, () -> { - for (var slot : task_slots) { - slot.setVisible(true); - } - }, () -> { - for (var slot : task_slots) { - slot.setVisible(false); - } - }); - - scroll_panel.setParent(frame); - scroll_panel.setDock(Dock.RIGHT); - scroll_panel.setupRowMultiplier(() -> { - if (tasks_tab.isActive()) { - return menu.getTasks().size() / GRID_WIDTH; - } - - return menu.getPatterns().size() / GRID_WIDTH; - }); - - var grid = new GridPanel(this, frame, 0, 0, GRID_WIDTH * AbstractSlotPanel.SIZE, 0, GRID_WIDTH, GRID_HEIGHT) { - @Override - protected boolean mouseScrolledInner(double x, double y, double scroll) { - return scroll_panel.mouseScrolledInner(x, y, scroll); - } - }; - - grid.setDock(Dock.LEFT); - grid.setDockMargin(4, 0, 0, 0); - - for (int i = 0; i < GRID_WIDTH * GRID_HEIGHT; i++) { - int slot = i; - - pattern_slots.add(new AbstractSlotPanel(this, grid, 0, 0) { - @Nonnull - @Override - protected ItemStack getItemStack() { - var slot1 = slot + scroll_panel.getScroll(menu.getPatterns().size() / GRID_WIDTH) * GRID_WIDTH; - - if (slot1 >= menu.getPatterns().size()) { - return ItemStack.EMPTY; - } - - return menu.getPatterns().get(slot1).stack(); - } - - @Nonnull - @Override - protected List getItemStackTooltip(@Nonnull ItemStack stack) { - var slot1 = slot + scroll_panel.getScroll(menu.getPatterns().size() / GRID_WIDTH) * GRID_WIDTH; - - if (slot1 >= menu.getPatterns().size()) { - return List.of(); - } - - return getPatternTooltip(super.getItemStackTooltip(stack), menu.getPatterns().get(slot1)); - } - - @Override - protected boolean mouseScrolledInner(double x, double y, double scroll) { - return scroll_panel.mouseScrolledInner(x, y, scroll); - } - - @Override - protected boolean mouseClickedInner(double x, double y, int flag) { - if (slot >= menu.getPatterns().size()) { - return true; - } - - openPattern(menu.getPatterns().get(slot)); - - return true; - } - }); - - task_slots.add(new AbstractSlotPanel(this, grid, 0, 0) { - @Nonnull - @Override - protected ItemStack getItemStack() { - var slot1 = slot + scroll_panel.getScroll(menu.getTasks().size() / GRID_WIDTH) * GRID_WIDTH; - - if (slot1 >= menu.getTasks().size()) { - return ItemStack.EMPTY; - } - - var task = menu.getTasks().get(slot1); - return task.stack(Math.max(task.required(), 1)); - } - - @Nonnull - @Override - protected List getItemStackTooltip(@Nonnull ItemStack stack) { - var slot1 = slot + scroll_panel.getScroll(menu.getTasks().size() / GRID_WIDTH) * GRID_WIDTH; - - if (slot1 >= menu.getTasks().size()) { - return List.of(); - } - - return getTaskTooltip(super.getItemStackTooltip(stack), menu.getTasks().get(slot1)); - } - - @Override - protected boolean mouseScrolledInner(double x, double y, double scroll) { - return scroll_panel.mouseScrolledInner(x, y, scroll); - } - - @Override - protected boolean mouseClickedInner(double x, double y, int flag) { - if (slot >= menu.getTasks().size()) { - return true; - } - - openTask(menu.getTasks().get(slot)); - - return true; - } - }); - } - - for (var slot : task_slots) { - slot.setVisible(false); - } - - return frame; - } - - private List getTaskTooltip(List input, MatterTask task) { - input.add(TranslatableComponent("otm.gui.matter_task.total", task.total()).withStyle(ChatFormatting.GRAY)); - input.add(TranslatableComponent("otm.gui.matter_task.required", task.required()).withStyle(ChatFormatting.GRAY)); - input.add(TranslatableComponent("otm.gui.matter_task.in_progress", task.in_progress()).withStyle(ChatFormatting.GRAY)); - input.add(TranslatableComponent("otm.gui.matter_task.finished", task.finished()).withStyle(ChatFormatting.GRAY)); - - return input; - } - - private List getPatternTooltip(List input, PatternState pattern) { - input.add(TranslatableComponent("otm.item.pattern.research", String.format("%.2f", pattern.research() * 100d)).withStyle(ChatFormatting.AQUA)); - - return input; - } - - private void openTask(MatterTask task) { - var task_frame = new FramePanel(this, null, 0, 0, 170, 40, TranslatableComponent("otm.container.matter_panel.task")) { - @Override - public void tick() { - super.tick(); - - if (!menu.getTasks().contains(task)) { - remove(); - } - } - }; - - var slot = new AbstractSlotPanel(this, task_frame, 0, 0) { - @Nonnull - @Override - protected ItemStack getItemStack() { - var task1_index = menu.getTasks().indexOf(task); - - if (task1_index != -1) { - var task1 = menu.getTasks().get(task1_index); - return task1.stack(Math.max(task1.required(), 1)); - } - - return ItemStack.EMPTY; - } - - @Nonnull - @Override - protected List getItemStackTooltip(@Nonnull ItemStack stack) { - var task1_index = menu.getTasks().indexOf(task); - List get_list = super.getItemStackTooltip(stack); - - if (task1_index != -1) { - getTaskTooltip(get_list, menu.getTasks().get(task1_index)); - } - - return get_list; - } - }; - - slot.setDock(Dock.LEFT); - - var button = new ButtonPanel(this, task_frame, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.close")); - button.setDock(Dock.RIGHT); - button.setDockMargin(2, 0, 0, 0); - button.bind(task_frame::remove); - - button = new ButtonPanel(this, task_frame, 0, 0, 80, 20, TranslatableComponent("otm.container.matter_panel.cancel_task")); - button.setDock(Dock.RIGHT); - button.setDockMargin(2, 0, 0, 0); - button.bind(() -> { - menu.requestTaskCancel(task.id()); - task_frame.remove(); - }); - - task_frame.toScreenCenter(); - addPanel(task_frame); - } - - private void openPattern(PatternState state) { - var pattern_frame = new FramePanel(this, null, 0, 0, MODAL_WIDTH, MODAL_HEIGHT, TranslatableComponent("otm.container.matter_panel.label")){ - @Override - public void tick() { - super.tick(); - - if (!menu.getPatterns().contains(state)) { - remove(); - } - } - }; - - var row_1 = new EditablePanel(this, pattern_frame); - var row_2 = new EditablePanel(this, pattern_frame); - var row_3 = new EditablePanel(this, pattern_frame); - var row_4 = new EditablePanel(this, pattern_frame); - - row_1.setDock(Dock.TOP); - row_2.setDock(Dock.TOP); - row_3.setDock(Dock.TOP); - row_4.setDock(Dock.TOP); - - row_1.setHeight(20); - row_2.setHeight(20); - row_3.setHeight(20); - row_4.setHeight(20); - - row_1.setDockMargin(0, 2, 0, 0); - row_2.setDockMargin(0, 2, 0, 0); - row_3.setDockMargin(0, 2, 0, 0); - row_4.setDockMargin(0, 2, 0, 0); - - var slot = new AbstractSlotPanel(this, row_2, 0, 0) { - @Nonnull - @Override - protected ItemStack getItemStack() { - return new ItemStack(state.item(), 1); - } - - @Nonnull - @Override - protected List getItemStackTooltip(@Nonnull ItemStack stack) { - return getPatternTooltip(super.getItemStackTooltip(stack), state); - } - }; - - var input_amount = new EditBoxPanel(this, row_2, 0, 0, 10, 20, TextComponent("Input amount")) { - @Override - protected void configureNew(@Nonnull EditBox widget, boolean recreation) { - super.configureNew(widget, recreation); - - widget.setMaxLength(6); - - if (!recreation) { - widget.setValue("1"); - } - } - - private void increase(int amount) { - int value = 1; - - try { - value = Integer.parseInt(getOrCreateWidget().getValue()); - } catch (Exception ignored) { - - } - - if (value == 1 && amount > 0) - getOrCreateWidget().setValue(Integer.toString(amount)); - else - getOrCreateWidget().setValue(Integer.toString(Math.max(1, Math.min(99999, value + amount)))); - } - }; - - var button = new ButtonPanel(this, row_1, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.increase_by", 8)); - button.bind(() -> input_amount.increase(8)); - button.setDock(Dock.RIGHT); - button.setDockMargin(2, 0, 0, 0); - - button = new ButtonPanel(this, row_1, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.increase_by", 64)); - button.setDock(Dock.RIGHT); - button.bind(() -> input_amount.increase(64)); - button.setDockMargin(2, 0, 0, 0); - - button = new ButtonPanel(this, row_1, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.increase_by", 256)); - button.setDock(Dock.RIGHT); - button.bind(() -> input_amount.increase(256)); - button.setDockMargin(2, 0, 0, 0); - - slot.setDock(Dock.LEFT); - slot.setDockMargin(0, 0, 4, 0); - input_amount.setDock(Dock.FILL); - - button = new ButtonPanel(this, row_3, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.decrease_by", 8)); - button.bind(() -> input_amount.increase(-8)); - button.setDock(Dock.RIGHT); - button.setDockMargin(2, 0, 0, 0); - - button = new ButtonPanel(this, row_3, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.decrease_by", 64)); - button.setDock(Dock.RIGHT); - button.bind(() -> input_amount.increase(-64)); - button.setDockMargin(2, 0, 0, 0); - - button = new ButtonPanel(this, row_3, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.decrease_by", 256)); - button.setDock(Dock.RIGHT); - button.bind(() -> input_amount.increase(-256)); - button.setDockMargin(2, 0, 0, 0); - - button = new ButtonPanel(this, row_4, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.cancel")); - button.setDock(Dock.RIGHT); - button.bind(pattern_frame::remove); - button.setDockMargin(2, 0, 0, 0); - - button = new ButtonPanel(this, row_4, 0, 0, 82, 20, TranslatableComponent("otm.container.matter_panel.send")); - button.setDock(Dock.RIGHT); - button.bind(() -> { - int value = 1; - - try { - value = Integer.parseInt(input_amount.getOrCreateWidget().getValue()); - } catch (Exception ignored) { - - } - - MenuNetworkChannel.INSTANCE.sendToServer(new ReplicationRequestPacket(state, value)); - pattern_frame.remove(); - }); - - button.setDockMargin(2, 0, 0, 0); - - addPanel(pattern_frame); - pattern_frame.toScreenCenter(); - popup(pattern_frame); - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/registry/MRecipes.java b/src/main/java/ru/dbotthepony/mc/otm/registry/MRecipes.java index 7c7b9b2c4..d90b6b9ad 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/registry/MRecipes.java +++ b/src/main/java/ru/dbotthepony/mc/otm/registry/MRecipes.java @@ -4,6 +4,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeType; +import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; @@ -35,8 +36,8 @@ public class MRecipes { typesRegistry.register(MNames.PLATE_PRESS, () -> PLATE_PRESS); } - public static void register() { - registry.register(FMLJavaModLoadingContext.get().getModEventBus()); - typesRegistry.register(FMLJavaModLoadingContext.get().getModEventBus()); + public static void register(IEventBus bus) { + registry.register(bus); + typesRegistry.register(bus); } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt deleted file mode 100644 index 4e8ea0863..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt +++ /dev/null @@ -1,213 +0,0 @@ - -@file:Suppress("unused") - -package ru.dbotthepony.mc.otm - -import com.google.common.collect.ImmutableList -import com.google.gson.JsonElement -import com.google.gson.JsonObject -import net.minecraft.core.BlockPos -import net.minecraft.core.Direction -import net.minecraft.core.Vec3i -import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.LongArrayTag -import net.minecraft.nbt.Tag -import net.minecraft.world.Container -import net.minecraft.world.entity.Entity -import net.minecraft.world.item.ItemStack -import net.minecraft.world.phys.Vec3 -import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.items.IItemHandler -import java.util.* -import kotlin.properties.ReadWriteProperty -import kotlin.reflect.KProperty - -operator fun Direction.unaryMinus(): Direction = this.opposite -operator fun Vec3i.unaryMinus(): Vec3i = Vec3i(-x, -y, -z) -operator fun BlockPos.unaryMinus(): BlockPos = BlockPos(-x, -y, -z) - -operator fun CompoundTag.set(index: String, value: Tag) = put(index, value) -operator fun CompoundTag.set(index: String, value: Int) = putInt(index, value) -operator fun CompoundTag.set(index: String, value: Byte) = putByte(index, value) -operator fun CompoundTag.set(index: String, value: Short) = putShort(index, value) -operator fun CompoundTag.set(index: String, value: Long) = putLong(index, value) -operator fun CompoundTag.set(index: String, value: Float) = putFloat(index, value) -operator fun CompoundTag.set(index: String, value: Double) = putDouble(index, value) -operator fun CompoundTag.set(index: String, value: String) = putString(index, value) -operator fun CompoundTag.set(index: String, value: Boolean) = putBoolean(index, value) -operator fun CompoundTag.set(index: String, value: ByteArray) = putByteArray(index, value) -operator fun CompoundTag.set(index: String, value: IntArray) = putIntArray(index, value) -operator fun CompoundTag.set(index: String, value: LongArray) = putLongArray(index, value) - -@JvmInline -value class CompoundTagInt(val tag: CompoundTag) : ReadWriteProperty { - override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getInt(property.name) - override fun setValue(thisRef: Any, property: KProperty<*>, value: Int) = tag.putInt(property.name, value) -} - -@JvmInline -value class CompoundTagLong(val tag: CompoundTag) : ReadWriteProperty { - override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getLong(property.name) - override fun setValue(thisRef: Any, property: KProperty<*>, value: Long) = tag.putLong(property.name, value) -} - -@JvmInline -value class CompoundTagByte(val tag: CompoundTag) : ReadWriteProperty { - override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getByte(property.name) - override fun setValue(thisRef: Any, property: KProperty<*>, value: Byte) = tag.putByte(property.name, value) -} - -@JvmInline -value class CompoundTagShort(val tag: CompoundTag) : ReadWriteProperty { - override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getShort(property.name) - override fun setValue(thisRef: Any, property: KProperty<*>, value: Short) = tag.putShort(property.name, value) -} - -@JvmInline -value class CompoundTagFloat(val tag: CompoundTag) : ReadWriteProperty { - override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getFloat(property.name) - override fun setValue(thisRef: Any, property: KProperty<*>, value: Float) = tag.putFloat(property.name, value) -} - -@JvmInline -value class CompoundTagBoolean(val tag: CompoundTag) : ReadWriteProperty { - override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getBoolean(property.name) - override fun setValue(thisRef: Any, property: KProperty<*>, value: Boolean) = tag.putBoolean(property.name, value) -} - -@JvmInline -value class CompoundTagDouble(val tag: CompoundTag) : ReadWriteProperty { - override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getDouble(property.name) - override fun setValue(thisRef: Any, property: KProperty<*>, value: Double) = tag.putDouble(property.name, value) -} - -@JvmInline -value class CompoundTagString(val tag: CompoundTag) : ReadWriteProperty { - override fun getValue(thisRef: Any, property: KProperty<*>): String = tag.getString(property.name) - override fun setValue(thisRef: Any, property: KProperty<*>, value: String) = tag.putString(property.name, value) -} - -val EMPTY_UUID = UUID(0L, 0L) - -@JvmInline -value class CompoundTagUUID(val tag: CompoundTag) : ReadWriteProperty { - override fun getValue(thisRef: Any, property: KProperty<*>) = (tag.get(property.name) as LongArrayTag?)?.asLongArray?.let { UUID(it[0], it[1]) } ?: EMPTY_UUID - override fun setValue(thisRef: Any, property: KProperty<*>, value: UUID) = tag.putLongArray(property.name, longArrayOf(value.mostSignificantBits, value.leastSignificantBits)) -} - -val CompoundTag.ints get() = CompoundTagInt(this) -val CompoundTag.longs get() = CompoundTagLong(this) -val CompoundTag.bytes get() = CompoundTagByte(this) -val CompoundTag.shorts get() = CompoundTagShort(this) -val CompoundTag.floats get() = CompoundTagFloat(this) -val CompoundTag.doubles get() = CompoundTagDouble(this) -val CompoundTag.booleans get() = CompoundTagBoolean(this) -val CompoundTag.strings get() = CompoundTagString(this) -val CompoundTag.uuids get() = CompoundTagUUID(this) - -operator fun Container.set(index: Int, value: ItemStack) = setItem(index, value) -operator fun Container.get(index: Int): ItemStack = getItem(index) -operator fun IItemHandler.get(index: Int): ItemStack = getStackInSlot(index) - -operator fun JsonObject.set(s: String, value: JsonElement) = add(s, value) - -inline fun CompoundTag.ifHas(s: String, consumer: (Tag) -> Unit) { - val tag = get(s) - - if (tag != null) { - consumer(tag) - } -} - -inline fun CompoundTag.ifHas(s: String, type: Byte, consumer: (Tag) -> Unit) { - val tag = get(s) - - if (tag != null && tag.id == type) { - consumer(tag) - } -} - -inline fun CompoundTag.ifHas(s: String, type: Class, consumer: (T) -> Unit) { - val tag = get(s) - - if (tag != null && tag::class.java === type) { - consumer(tag as T) - } -} - -fun LazyOptional.orNull(): T? { - if (!isPresent) { - return null - } - - return resolve().orElse(null) -} - -fun LazyOptional.orThrow(): T { - if (!isPresent) { - throw IllegalStateException("Capability was expected to be not null") - } - - return resolve().orElse(null) ?: throw IllegalStateException("Capability was expected to be not null") -} - -inline fun LazyOptional.ifPresentK(lambda: (T) -> Unit) { - if (isPresent) { - val value = resolve().orElse(null) ?: throw IllegalStateException("Capability was expected to be not null") - lambda.invoke(value) - } -} - -val ItemStack.tagNotNull: CompoundTag get() = orCreateTag - -inline var Entity.position: Vec3 - get() = position() - set(value) { setPos(value) } - -inline val > T.next: T get() { - val values = enumValues() - val next = (ordinal + 1) % values.size - return values[next] -} - -inline val > T.prev: T get() { - val values = enumValues() - var next = ordinal - 1 - - if (next < 0) { - next = values.size - 1 - } - - return values[next] -} - -fun > T.next(values: Array): T { - val next = (ordinal + 1) % values.size - return values[next] -} - -fun > T.prev(values: Array): T { - var next = ordinal - 1 - - if (next < 0) { - next = values.size - 1 - } - - return values[next] -} - -inline fun ImmutableList(size: Int, initializer: (index: Int) -> T): ImmutableList { - require(size >= 0) { "Invalid list size $size" } - - return when (size) { - 0 -> ImmutableList.of() - 1 -> ImmutableList.of(initializer(0)) - else -> ImmutableList.Builder().let { - for (i in 0 until size) { - it.add(initializer(i)) - } - - it.build() - } - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt index 076683ed5..284cc4c67 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/GlobalEventHandler.kt @@ -118,6 +118,8 @@ private var _server: MinecraftServer? = null private var _serverThread: Thread? = null private var _clientThread: Thread? = null +val isClient: Boolean get() = _clientThread !== null + fun recordClientThread() { if (_clientThread != null) { throw IllegalStateException("Already have client channel") @@ -127,13 +129,13 @@ fun recordClientThread() { } fun runIfClient(lambda: () -> Unit) { - if (_clientThread !== null) { + if (isClient) { lambda.invoke() } } fun runIfClient(value: V, lambda: () -> V): V { - if (_clientThread !== null) { + if (isClient) { return lambda.invoke() } @@ -178,7 +180,6 @@ interface IConditionalTickable : ITickable { val canTick: Boolean } -@SubscribeEvent(priority = EventPriority.LOWEST) fun onServerTick(event: ServerTickEvent) { if (event.phase === TickEvent.Phase.START) { preServerTickTimers.tick() @@ -253,7 +254,6 @@ fun addPostServerTickerOnce(ticker: ITickable) { postServerTickOnce.add(ticker) } -@SubscribeEvent(priority = EventPriority.LOWEST) fun onWorldTick(event: LevelTickEvent) { if (event.phase === TickEvent.Phase.START) { val it = preWorldTick[event.level] @@ -353,7 +353,6 @@ private fun clear() { postWorldTickOnce.clear() } -@SubscribeEvent(priority = EventPriority.HIGHEST) fun onServerStarting(event: ServerAboutToStartEvent) { clear() SERVER_IS_DYING = false @@ -361,13 +360,11 @@ fun onServerStarting(event: ServerAboutToStartEvent) { _serverThread = Thread.currentThread() } -@SubscribeEvent(priority = EventPriority.HIGHEST) fun onServerStopping(event: ServerStoppingEvent) { clear() SERVER_IS_DYING = true } -@SubscribeEvent(priority = EventPriority.HIGHEST) fun onServerStopped(event: ServerStoppedEvent) { if (!SERVER_IS_DYING) { LOGGER.fatal("ServerStoppingEvent did not fire. If server has crashed this is normal. However, if server finished it's work 'gracefully' this is a bug.") 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 28bc2521b..5c335adb3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt @@ -4,9 +4,10 @@ import net.minecraft.nbt.CompoundTag import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.event.entity.living.LivingHurtEvent import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability -import ru.dbotthepony.mc.otm.readNbt -import ru.dbotthepony.mc.otm.set -import ru.dbotthepony.mc.otm.writeNbt +import ru.dbotthepony.mc.otm.core.readNbt +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set +import ru.dbotthepony.mc.otm.core.writeNbt import java.io.InputStream import java.io.OutputStream diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeatureType.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeatureType.kt index f2e501014..c4630ae21 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeatureType.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeatureType.kt @@ -5,7 +5,7 @@ import net.minecraft.network.chat.ComponentContents import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.contents.TranslatableContents import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability -import ru.dbotthepony.mc.otm.getKeyNullable +import ru.dbotthepony.mc.otm.core.getKeyNullable import ru.dbotthepony.mc.otm.registry.MRegistry open class AndroidFeatureType { 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 97860c3dc..9d1181152 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt @@ -7,9 +7,10 @@ import net.minecraft.world.item.ItemStack import net.minecraftforge.common.util.INBTSerializable import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.client.render.SkinElement -import ru.dbotthepony.mc.otm.readNbt -import ru.dbotthepony.mc.otm.set -import ru.dbotthepony.mc.otm.writeNbt +import ru.dbotthepony.mc.otm.core.readNbt +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set +import ru.dbotthepony.mc.otm.core.writeNbt import java.io.InputStream import java.io.OutputStream diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.kt index 43c6b481d..4f9d5ca5d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchBuilder.kt @@ -6,9 +6,10 @@ import net.minecraft.ChatFormatting import net.minecraft.network.chat.Component import net.minecraft.resources.ResourceLocation import net.minecraft.world.item.ItemStack -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.render.SkinElement import ru.dbotthepony.mc.otm.container.iterator +import ru.dbotthepony.mc.otm.core.nonEmpty import ru.dbotthepony.mc.otm.registry.MRegistry import kotlin.collections.ArrayList @@ -260,7 +261,7 @@ class AndroidResearchBuilder( for (item in items) { var required = item.count - val iterator = capability.ply.inventory.iterator() + val iterator = capability.ply.inventory.iterator().nonEmpty() for (invItem in iterator) { if (ItemStack.isSameItemSameTags(invItem, item)) { @@ -335,7 +336,8 @@ class AndroidResearchBuilder( } if (experience != 0) { - builder.add(TranslatableComponent("otm.android_station.research.xp_cost", experience).withStyle( + builder.add( + TranslatableComponent("otm.android_station.research.xp_cost", experience).withStyle( if (capability.ply.experienceLevel >= experience) ChatFormatting.DARK_GREEN else @@ -346,7 +348,8 @@ class AndroidResearchBuilder( for (value in this.type.flatPrerequisites) { val instance = capability.getResearch(value) - builder.add(TranslatableComponent("android_research.status.requires", instance.screenTooltipHeader).withStyle( + builder.add( + TranslatableComponent("android_research.status.requires", instance.screenTooltipHeader).withStyle( if (instance.isResearched) ChatFormatting.DARK_GREEN else diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt index 56e9ea9fc..762070f98 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt @@ -6,9 +6,9 @@ import net.minecraft.network.chat.Component import net.minecraft.network.chat.ComponentContents import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.contents.TranslatableContents -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability -import ru.dbotthepony.mc.otm.getKeyNullable +import ru.dbotthepony.mc.otm.core.getKeyNullable import ru.dbotthepony.mc.otm.registry.MRegistry import java.util.* import kotlin.collections.HashSet diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt index a6c46cf51..bc61f5055 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt @@ -9,7 +9,8 @@ import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.StatNames -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set import kotlin.math.roundToInt class NanobotsArmor(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt index aee96f7d8..611d9e688 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt @@ -8,7 +8,8 @@ import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.StatNames -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set import kotlin.math.roundToInt class NanobotsRegeneration(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_REGENERATION, android) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/AndroidStationBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/AndroidStationBlock.kt index 779fe6683..8c958eb0a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/AndroidStationBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/AndroidStationBlock.kt @@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import ru.dbotthepony.mc.otm.block.entity.AndroidStationBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability -import ru.dbotthepony.mc.otm.orNull +import ru.dbotthepony.mc.otm.core.orNull import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/ChemicalGeneratorBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/ChemicalGeneratorBlock.kt index bcc9e7de2..79784fab9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/ChemicalGeneratorBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/ChemicalGeneratorBlock.kt @@ -15,7 +15,7 @@ import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import ru.dbotthepony.mc.otm.addPreWorldTickerOnce import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/GravitationStabilizerBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/GravitationStabilizerBlock.kt index 1ab676aca..5e1766dee 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/GravitationStabilizerBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/GravitationStabilizerBlock.kt @@ -25,7 +25,7 @@ import net.minecraft.world.phys.shapes.VoxelShape import ru.dbotthepony.mc.otm.addPreWorldTickerOnce import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.core.plus import ru.dbotthepony.mc.otm.core.times import ru.dbotthepony.mc.otm.registry.MBlockEntities diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/PlatePressBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/PlatePressBlock.kt index 31fedcad5..448956867 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/PlatePressBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/PlatePressBlock.kt @@ -14,7 +14,7 @@ import net.minecraft.world.level.block.state.StateDefinition import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import ru.dbotthepony.mc.otm.block.entity.PlatePressBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt index ca6bb8e4a..dadc3dd85 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt @@ -9,7 +9,7 @@ import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.phys.AABB -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.core.ImpreciseFraction diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt index 9d45286d8..b6a0fea83 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt @@ -22,7 +22,7 @@ import ru.dbotthepony.mc.otm.block.BatteryBankBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.container.MatteryContainer -import ru.dbotthepony.mc.otm.core.ImpreciseFraction +import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.menu.BatteryBankMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities import javax.annotation.ParametersAreNonnullByDefault diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/CargoCrateBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/CargoCrateBlockEntity.kt index 4eacf3bb0..42810e5cb 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/CargoCrateBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/CargoCrateBlockEntity.kt @@ -12,13 +12,13 @@ import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.LazyOptional -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.CargoCrateBlock import ru.dbotthepony.mc.otm.container.MatteryContainer -import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.menu.CargoCrateMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set class CargoCrateBlockEntity( p_155229_: BlockPos, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt index aa1909a33..7cc7b630e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt @@ -19,11 +19,9 @@ import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.energy.IEnergyStorage import ru.dbotthepony.mc.otm.* import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.container.MatteryContainer -import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.core.plus +import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.menu.ChemicalGeneratorMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities import java.lang.ref.WeakReference diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt index 0ca893883..ccf4efca9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt @@ -25,7 +25,7 @@ import ru.dbotthepony.mc.otm.* import ru.dbotthepony.mc.otm.block.EnergyCounterBlock import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.compat.mekanism.MatteryToMekanismEnergyWrapper -import ru.dbotthepony.mc.otm.core.ImpreciseFraction +import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.network.WorldNetworkChannel diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/GravitationStabilizerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/GravitationStabilizerBlockEntity.kt index bbeb3c1d6..9a14c3332 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/GravitationStabilizerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/GravitationStabilizerBlockEntity.kt @@ -9,12 +9,11 @@ import net.minecraft.world.level.Level import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.phys.AABB -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.BlockGravitationStabilizer import ru.dbotthepony.mc.otm.block.BlockGravitationStabilizerLens import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.core.plus import ru.dbotthepony.mc.otm.core.times import ru.dbotthepony.mc.otm.registry.MBlockEntities 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 d4b280222..95c0ad057 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 @@ -23,8 +23,9 @@ import net.minecraft.network.chat.Component import net.minecraft.world.level.Level import net.minecraftforge.common.capabilities.Capability import ru.dbotthepony.mc.otm.addPreWorldTickerOnce -import ru.dbotthepony.mc.otm.ifHas -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.core.ifHas +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(p_155228_, p_155229_, p_155230_), MenuProvider { var customDisplayName: Component? = null diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt index a097856de..ae82e2dd0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryPoweredBlockEntity.kt @@ -8,13 +8,13 @@ import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.energy.CapabilityEnergy import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.ifHas -import ru.dbotthepony.mc.otm.ifPresentK -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.core.ifHas +import ru.dbotthepony.mc.otm.core.ifPresentK +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryBlockEntity(p_155228_, p_155229_, p_155230_) { abstract val energy: BlockEnergyStorageImpl diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt new file mode 100644 index 000000000..4ddaf9721 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryWorkerBlockEntity.kt @@ -0,0 +1,342 @@ +package ru.dbotthepony.mc.otm.block.entity + +import net.minecraft.world.level.block.entity.BlockEntityType +import net.minecraft.core.BlockPos +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.nbt.CompoundTag +import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.block.Block +import ru.dbotthepony.mc.otm.core.* +import ru.dbotthepony.mc.otm.core.map + +private fun isReason(status: Any?, reason: Any) = status == null || status == reason + +abstract class MatteryWorkerBlockEntity( + type: BlockEntityType<*>, + blockPos: BlockPos, + blockState: BlockState, + val jobDeserializer: (tag: CompoundTag) -> JobType? +) : MatteryPoweredBlockEntity(type, blockPos, blockState) { + open class Job( + open val ticks: Double, + open val powerUsage: ImpreciseFraction = ImpreciseFraction.ZERO + ) { + constructor( + tag: CompoundTag + ) : this(tag.getDouble("ticks"), tag.getImpreciseFraction("power")) + + open fun serializeNBT(): CompoundTag { + return CompoundTag().also { + it["ticks"] = ticks + it["power"] = powerUsage + } + } + } + + @Suppress("LeakingThis") + open class ItemJob : Job { + open val itemStack: ItemStack + + constructor( + itemStack: ItemStack, + ticks: Double, + power: ImpreciseFraction = ImpreciseFraction.ZERO + ) : super(ticks, power) { + this.itemStack = itemStack + } + + constructor( + tag: CompoundTag + ) : super(tag) { + this.itemStack = (tag["item"] as? CompoundTag)?.let { ItemStack.of(it) } ?: ItemStack.EMPTY + } + + override fun serializeNBT(): CompoundTag { + return super.serializeNBT().also { + it["item"] = itemStack.serializeNBT() + } + } + } + + enum class IdleReason { + ITEM, + POWER, + MATTER, + + /** + * Observing external factor, such as waiting for matter/item network tasks + */ + OBSERVING + } + + data class Status(val success: Boolean, val throttleTicks: Int = 0, val idleReason: IdleReason? = null) { + companion object { + val SUCCESS = Status(true) + val FAILURE = Status(false) + val FAILURE_ITEM = Status(false, 20, IdleReason.ITEM) + val FAILURE_MATTER = Status(false, 20, IdleReason.MATTER) + val FAILURE_WAIT = Status(false, 100) + val FAILURE_WAIT_FAST = Status(false, 20) + } + } + + var workTicks = 0.0 + protected set + + var throttleTicks = 0 + protected set + + var currentJob: JobType? = null + protected set + + /** + * Can be whatever you want, but [IdleReason] certainly contains all cases + */ + var idleReason: Any? = null + private set + + var isIdling = false + protected set + + val isUnableToProcess: Boolean get() = throttleTicks > 0 + + val workProgress: Float + get() { + val currentJob = currentJob ?: return 0.0f + return (workTicks / currentJob.ticks).coerceAtMost(1.0).toFloat() + } + + override fun saveAdditional(nbt: CompoundTag) { + super.saveAdditional(nbt) + nbt["work_ticks"] = workTicks + currentJob?.let { nbt["job"] = it.serializeNBT() } + } + + override fun load(nbt: CompoundTag) { + super.load(nbt) + + workTicks = nbt.getDouble("work_ticks") + currentJob = nbt.map("job", jobDeserializer::invoke) + + if (currentJob == null) + workTicks = 0.0 + } + + override fun setChanged() { + super.setChanged() + isIdling = false + } + + override fun setChangedLight() { + super.setChangedLight() + isIdling = false + } + + protected fun powerLevelUpdated() { + super.setChangedLight() + + if (isReason(idleReason, IdleReason.POWER)) { + isIdling = false + throttleTicks = 0 + } + } + + protected fun itemContainerUpdated() { + super.setChanged() + + if (isReason(idleReason, IdleReason.ITEM)) { + isIdling = false + throttleTicks = 0 + } + } + + protected fun matterLevelUpdated() { + super.setChangedLight() + + if (isReason(idleReason, IdleReason.MATTER)) { + isIdling = false + throttleTicks = 0 + } + } + + /** + * Called whenever reaching desired amount of ticks at job + */ + protected abstract fun onJobFinish(job: JobType): Status + + /** + * [Pair.second] is reason why job can't be performed + * + * If not null, it is written to [idleReason] + */ + protected abstract fun computeNextJob(): Pair + + protected open fun onWorkTick(requiredPower: ImpreciseFraction, extractedPower: ImpreciseFraction, ticksAdvanced: Double): Status { + return Status.SUCCESS + } + + private var idleTicksAnim = 0 + private var workingTicksAnim = 0 + private var errorTicksAnim = 0 + + override fun redstoneStatusUpdated(new_blocked: Boolean, old_blocked: Boolean) { + super.redstoneStatusUpdated(new_blocked, old_blocked) + isIdling = new_blocked + } + + protected fun workerLoop() { + if (errorTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.ERROR) { + level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.ERROR), Block.UPDATE_CLIENTS) + } + + if (throttleTicks > 0) { + workingTicksAnim = 0 + idleTicksAnim = 0 + throttleTicks-- + errorTicksAnim++ + + if (throttleTicks > 0) + return + else + isIdling = false + } + + if (isIdling) { + workingTicksAnim = 0 + errorTicksAnim = 0 + idleTicksAnim++ + + if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue( + WorkerState.WORKER_STATE + ) != WorkerState.IDLE + ) { + level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS) + } + + return + } + + var availableTicks = 1.0 + + while (!isIdling && weakGreaterThan(availableTicks, 0.0)) { + if (isBlockedByRedstone) { + isIdling = true + break + } + + var currentJob = currentJob + + if (currentJob == null) { + if (isBlockedByRedstone) { + isIdling = true + break + } + + val (job, reason) = computeNextJob() + + if (job == null) { + idleReason = reason + isIdling = reason != null + workingTicksAnim = 0 + break + } + + this.currentJob = job + currentJob = job + } + + if (!currentJob.powerUsage.isZero && energy.batteryLevel.isZero) { + idleReason = IdleReason.POWER + isIdling = true + idleTicksAnim++ + + if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue( + WorkerState.WORKER_STATE + ) != WorkerState.IDLE + ) { + level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS) + } + + break + } + + idleTicksAnim = 0 + + if (weakLessThan(workTicks, currentJob.ticks)) { + val ticksLeft = currentJob.ticks - workTicks + val ticksAdvanced: Double + + var requiredPower: ImpreciseFraction? = null + var extractedPower: ImpreciseFraction? = null + + if (currentJob.powerUsage.isZero) { + ticksAdvanced = availableTicks.coerceAtMost(ticksLeft) + } else { + requiredPower = currentJob.powerUsage * ticksLeft.coerceAtMost(availableTicks) + extractedPower = energy.extractEnergyInner(requiredPower, true) + ticksAdvanced = (extractedPower / requiredPower).toDouble().coerceAtMost(ticksLeft).coerceAtMost(availableTicks) + } + + if (weakEqualDoubles(ticksAdvanced, 0.0)) { + break + } + + val status = onWorkTick(requiredPower ?: ImpreciseFraction.ZERO, extractedPower ?: ImpreciseFraction.ZERO, ticksAdvanced) + + if (!status.success) { + throttleTicks += status.throttleTicks + + if (status.idleReason != null) { + idleReason = status.idleReason + isIdling = true + } + + break + } + + workingTicksAnim++ + errorTicksAnim = 0 + + workTicks += ticksAdvanced + availableTicks -= ticksAdvanced + + if (extractedPower != null) { + energy.extractEnergyInner(extractedPower, false) + } + + continue + } + + val status = onJobFinish(currentJob) + + if (status.success) { + this.currentJob = null + workTicks = 0.0 + errorTicksAnim = 0 + } else { + throttleTicks += status.throttleTicks + + if (status.idleReason != null) { + idleReason = status.idleReason + isIdling = true + } + + errorTicksAnim++ + } + } + + if (workingTicksAnim > 20 && + errorTicksAnim == 0 && + blockState.hasProperty(WorkerState.WORKER_STATE) && + blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.WORKING + ) + { + level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS) + } + } + + fun basicTicker() { + batteryChargeLoop() + workerLoop() + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/PatternStorageBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/PatternStorageBlockEntity.kt index d531dbaa1..2296f4f5f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/PatternStorageBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/PatternStorageBlockEntity.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.mc.otm.block.entity +import com.google.common.collect.Streams import javax.annotation.ParametersAreNonnullByDefault import net.minecraft.core.BlockPos import net.minecraft.world.level.block.state.BlockState @@ -9,7 +10,6 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.block.matter.PatternStorageBlock import net.minecraft.nbt.CompoundTag import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.items.CapabilityItemHandler import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu @@ -21,15 +21,19 @@ import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.Level import net.minecraft.world.level.block.Block import net.minecraftforge.common.capabilities.Capability -import ru.dbotthepony.mc.otm.TranslatableComponent +import net.minecraftforge.common.capabilities.ForgeCapabilities +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.capability.matter.* +import ru.dbotthepony.mc.otm.container.forEachCapability +import ru.dbotthepony.mc.otm.core.iterator import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph -import ru.dbotthepony.mc.otm.ifHas +import ru.dbotthepony.mc.otm.core.ifHas import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.core.set import java.util.ArrayList +import java.util.stream.Stream @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault @@ -48,13 +52,13 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : if (grid != null && !ItemStack.isSameItemSameTags(new, old)) { if (!old.isEmpty) { old.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage -> - cap.storedPatterns.forEach { state: PatternState? -> grid.onPatternRemoved(state!!) } + cap.storedPatterns.forEach { grid.onPatternRemoved(it) } } } if (!new.isEmpty) { new.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage -> - cap.storedPatterns.forEach { state: PatternState? -> grid.onPatternAdded(state!!) } + cap.storedPatterns.forEach { grid.onPatternAdded(it) } } } @@ -130,9 +134,9 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : override fun getCapability(cap: Capability, side: Direction?): LazyOptional { if (valid) { - if (cap === MatteryCapability.PATTERN) return resolverPatterns.cast() - if (cap === MatteryCapability.MATTER_NODE) return resolverNode.cast() - if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return resolverItem.get().cast() + if (cap == MatteryCapability.PATTERN) return resolverPatterns.cast() + if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast() + if (cap == ForgeCapabilities.ITEM_HANDLER) return resolverItem.get().cast() } return super.getCapability(cap, side) @@ -145,16 +149,20 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : return PatternStorageMenu(containerID, inventory, this) } - override val storedPatterns: Collection get() { - val list = ArrayList() - patterns.consumeCapability(MatteryCapability.PATTERN) { capability: IPatternStorage -> list.addAll(capability.storedPatterns) } - return list + override val storedPatterns: Stream get() { + val streams = ArrayList>() + + for (provider in patterns.iterator(MatteryCapability.PATTERN)) { + streams.add(provider.second.storedPatterns) + } + + return Streams.concat(*streams.toTypedArray()) } override val capacity: Int get() { var stored = 0L - for (pattern in patterns.capabilityIterator(MatteryCapability.PATTERN)) + for ((_, pattern) in patterns.iterator(MatteryCapability.PATTERN)) stored += pattern.capacity.toLong() return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt() @@ -163,7 +171,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : override val stored: Int get() { var stored = 0L - for (pattern in patterns.capabilityIterator(MatteryCapability.PATTERN)) + for ((_, pattern) in patterns.iterator(MatteryCapability.PATTERN)) stored += pattern.stored.toLong() return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt() @@ -174,9 +182,9 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : matterNode.destroy(::MatterNetworkGraph) } - override fun insertPattern(pattern: PatternState, only_update: Boolean, simulate: Boolean): PatternInsertStatus { - for (storage in patterns.capabilityIterator(MatteryCapability.PATTERN)) { - val status = storage.insertPattern(pattern, only_update, simulate) + override fun insertPattern(pattern: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus { + for (pair in patterns.iterator(MatteryCapability.PATTERN)) { + val status = pair.second.insertPattern(pattern, onlyUpdate, simulate) if (!status.isFailed) { if (!simulate) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/PlatePressBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/PlatePressBlockEntity.kt index c02389e33..85a24a20b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/PlatePressBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/PlatePressBlockEntity.kt @@ -10,12 +10,9 @@ import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.item.ItemStack import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.items.CapabilityItemHandler -import ru.dbotthepony.mc.otm.TranslatableComponent -import ru.dbotthepony.mc.otm.block.entity.worker.MatteryWorkerBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJob -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJobStatus +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainerFilter @@ -23,9 +20,13 @@ import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.menu.PlatePressMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MRecipes -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set -class PlatePressBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryWorkerBlockEntity(MBlockEntities.PLATE_PRESS, p_155229_, p_155230_) { +class PlatePressBlockEntity( + p_155229_: BlockPos, + p_155230_: BlockState +) : MatteryWorkerBlockEntity(MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ::ItemJob) { val container = MatteryContainer(this::setChangedLight, 2) override val energy = WorkerEnergyStorage(this::setChangedLight) @@ -50,7 +51,7 @@ class PlatePressBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matter } override fun getCapability(cap: Capability, side: Direction?): LazyOptional { - if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + if (cap == ForgeCapabilities.ITEM_HANDLER) return itemHandler.get().cast() return super.getCapability(cap, side) @@ -73,32 +74,24 @@ class PlatePressBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matter return PlatePressMenu(containerID, inventory, this) } - override fun onJobFinish(job: WorkerJob): WorkerJobStatus { - val resultTag = job.data["result"] as? CompoundTag ?: return WorkerJobStatus() - val result = ItemStack.of(resultTag) + override fun onJobFinish(job: ItemJob): Status { + if (job.itemStack.isEmpty) + return Status.SUCCESS - if (result.isEmpty) - return WorkerJobStatus() + if (!container.fullyAddItem(job.itemStack, start = SLOT_OUTPUT, end = SLOT_OUTPUT)) + return Status.FAILURE_ITEM - if (!container.fullyAddItem(result, start = SLOT_OUTPUT, end = SLOT_OUTPUT)) { - return WorkerJobStatus(false, 20) - } - - return WorkerJobStatus() + return Status.SUCCESS } - override fun computeNextJob(): WorkerJob? { - val level = level ?: return null - val recipe = level.recipeManager.getRecipeFor(MRecipes.PLATE_PRESS, container, level).orElse(null) ?: return null + override fun computeNextJob(): Pair { + if (energy.batteryLevel.isZero) { + return null to IdleReason.POWER + } - val copy = container[SLOT_INPUT].copy() + val recipe = level?.recipeManager?.getRecipeFor(MRecipes.PLATE_PRESS, container, level!!)?.orElse(null) ?: return null to IdleReason.ITEM container[SLOT_INPUT].shrink(1) - container.setChanged(SLOT_INPUT) - copy.count = 1 - - return WorkerJob(copy, recipe.workTime.toDouble(), BASELINE_CONSUMPTION, CompoundTag().also { - it["result"] = recipe.resultItem.serializeNBT() - }) + return ItemJob(recipe.resultItem, recipe.workTime.toDouble(), BASELINE_CONSUMPTION) to null } companion object { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneSetting.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneSetting.kt index bbc5a14a3..4c353f217 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneSetting.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/RedstoneSetting.kt @@ -1,7 +1,7 @@ package ru.dbotthepony.mc.otm.block.entity import net.minecraft.network.chat.Component -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent enum class RedstoneSetting(val label: Component, val description: Component) { IGNORED(TranslatableComponent("otm.gui.redstone.ignored"), TranslatableComponent("otm.gui.redstone.ignored.description")), diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/WorkerState.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/WorkerState.kt new file mode 100644 index 000000000..2c592bb86 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/WorkerState.kt @@ -0,0 +1,21 @@ +package ru.dbotthepony.mc.otm.block.entity + +import net.minecraft.util.StringRepresentable +import net.minecraft.world.level.block.state.properties.EnumProperty + +enum class WorkerState : StringRepresentable { + IDLE, + WORKING, + ERROR; + + companion object { + @JvmField + val WORKER_STATE: EnumProperty = EnumProperty.create("worker", WorkerState::class.java) + @JvmField + val SEMI_WORKER_STATE: EnumProperty = EnumProperty.create("worker", WorkerState::class.java, IDLE, WORKING) + } + + override fun getSerializedName(): String { + return if (this == IDLE) "idle" else if (this == WORKING) "working" else "error" + } +} 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 f9f828478..e5d9fd8c2 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 @@ -31,7 +31,8 @@ import ru.dbotthepony.mc.otm.matter.getMatterValue import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MRegistry -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set import kotlin.math.roundToInt import kotlin.math.sqrt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/Explosions.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/Explosions.kt index c5cb83b06..128e2bd75 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/Explosions.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/Explosions.kt @@ -23,7 +23,6 @@ import ru.dbotthepony.mc.otm.block.BlockExplosionDebugger import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.Vector import ru.dbotthepony.mc.otm.registry.MRegistry -import ru.dbotthepony.mc.otm.set import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashMap diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt index 7d42b525a..54c36c604 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt @@ -15,25 +15,22 @@ import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.items.CapabilityItemHandler -import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler import ru.dbotthepony.mc.otm.capability.matter.MatterDirection import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerImpl import ru.dbotthepony.mc.otm.container.MatteryContainer -import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph -import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu -import ru.dbotthepony.mc.otm.orNull import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.* class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, p_155229_, p_155230_), IMatterGraphNode { 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 5a87cf830..55f026f69 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 @@ -15,7 +15,7 @@ import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.util.LazyOptional -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.BatteryBankBlock import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability @@ -28,7 +28,8 @@ import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.menu.MatterCapacitorBankMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set import javax.annotation.ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt index 1b97ca714..94990d288 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt @@ -12,24 +12,22 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.items.CapabilityItemHandler import net.minecraftforge.items.IItemHandler -import ru.dbotthepony.mc.otm.TranslatableComponent -import ru.dbotthepony.mc.otm.block.entity.worker.MatteryWorkerBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJob -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJobStatus +import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler import ru.dbotthepony.mc.otm.capability.matter.MatterDirection import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerImpl import ru.dbotthepony.mc.otm.container.MatteryContainer -import ru.dbotthepony.mc.otm.core.ImpreciseFraction +import ru.dbotthepony.mc.otm.container.MatteryContainerFilter +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph -import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.item.MatterDustItem import ru.dbotthepony.mc.otm.matter.baselineComplexityDecomposeTicks import ru.dbotthepony.mc.otm.matter.canDecompose @@ -37,7 +35,6 @@ import ru.dbotthepony.mc.otm.matter.getMatterValue import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MItems -import ru.dbotthepony.mc.otm.set fun moveMatterAsDustIntoContainer(_matterValue: ImpreciseFraction, container: MatteryContainer, OUTPUT_DUST_MAIN: Int, OUTPUT_DUST_STACKING: Int): ImpreciseFraction { var matterValue = _matterValue @@ -93,7 +90,29 @@ fun moveMatterAsDustIntoContainer(_matterValue: ImpreciseFraction, container: Ma } class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) - : MatteryWorkerBlockEntity(MBlockEntities.MATTER_DECOMPOSER, pos, state), IMatterGraphNode { + : MatteryWorkerBlockEntity(MBlockEntities.MATTER_DECOMPOSER, pos, state, ::DecomposerJob), IMatterGraphNode { + + class DecomposerJob : Job { + val toDust: Boolean + var matterValue: ImpreciseFraction + + constructor(tag: CompoundTag) : super(tag) { + toDust = tag.getBoolean("to_dust") + matterValue = tag.getImpreciseFraction("value") + } + + constructor(toDust: Boolean, matterValue: ImpreciseFraction, ticks: Double) : super(ticks, BASE_CONSUMPTION) { + this.toDust = toDust + this.matterValue = matterValue + } + + override fun serializeNBT(): CompoundTag { + return super.serializeNBT().also { + it["to_dust"] = toDust + it["value"] = matterValue + } + } + } override val energy = WorkerEnergyStorage(this, ENERGY_STORAGE, MAX_IO) private var valid = true @@ -110,13 +129,18 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) private var resolverNode = LazyOptional.of { this } // вход, выход - @JvmField val container = MatteryContainer(this::setChangedLight, 3) private val itemHandler = LazyOptional.of { - container.handler( - { slot: Int, stack: ItemStack -> slot == INPUT_SLOT && canDecompose(stack) }, - { slot: Int, _: Int, _: ItemStack -> slot != INPUT_SLOT }) + container.handler(object : MatteryContainerFilter { + override fun canInsert(slot: Int, stack: ItemStack): Boolean { + return slot == INPUT_SLOT && canDecompose(stack) + } + + override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean { + return slot != INPUT_SLOT + } + }) } override val defaultDisplayName: Component @@ -156,39 +180,35 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) override fun getCapability(cap: Capability, side: Direction?): LazyOptional { if (valid) { - if (cap === MatteryCapability.MATTER) return resolverMatter.cast() - if (cap === MatteryCapability.MATTER_NODE) return resolverNode.cast() - if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return itemHandler.cast() + if (cap == MatteryCapability.MATTER) return resolverMatter.cast() + if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast() + if (cap == ForgeCapabilities.ITEM_HANDLER) return itemHandler.cast() } return super.getCapability(cap, side) } - override fun onJobFinish(job: WorkerJob): WorkerJobStatus { - var matterValue = ImpreciseFraction.deserializeNBT(job.data["value"]) + override fun onJobFinish(job: DecomposerJob): Status { + if (job.toDust) { + job.matterValue = moveMatterAsDustIntoContainer(job.matterValue, container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING) - if (job.data.getBoolean("to_dust")) { - matterValue = moveMatterAsDustIntoContainer(matterValue, container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING) - - if (!matterValue.isZero) { - job.data["value"] = matterValue.serializeNBT() - return WorkerJobStatus(20) + if (!job.matterValue.isZero) { + return Status.FAILURE_WAIT_FAST } - return WorkerJobStatus() + return Status.SUCCESS } - matterValue -= matter.receiveMatterInner(matterValue, false) + job.matterValue -= matter.receiveMatterInner(job.matterValue, false) - if (matterValue.isPositive) { - job.data["value"] = matterValue.serializeNBT() - return WorkerJobStatus(false, 20) + if (job.matterValue.isPositive) { + return Status.FAILURE_MATTER } - return WorkerJobStatus() + return Status.SUCCESS } - override fun computeNextJob(): WorkerJob? { + override fun computeNextJob(): Pair { val stack = container[INPUT_SLOT] if (!stack.isEmpty) { @@ -197,19 +217,13 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) if (canDecompose(copy)) { val matter = getMatterValue(copy) + stack.count-- - if (!matter.isZero) { - stack.count-- - - return WorkerJob(copy, matter.complexity * baselineComplexityDecomposeTicks, BASE_CONSUMPTION, CompoundTag().also { - it["to_dust"] = (level?.random?.nextDouble() ?: 1.0) <= 0.2 - it["value"] = matter.value.serializeNBT() - }) - } + return DecomposerJob((level?.random?.nextDouble() ?: 1.0) <= 0.2, matter.value, matter.complexity * baselineComplexityDecomposeTicks) to null } } - return null + return null to IdleReason.ITEM } override fun setRemoved() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt index ac0da2868..6cd1340d2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt @@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.block.entity.matter import net.minecraft.core.BlockPos import net.minecraft.core.Direction import net.minecraft.world.level.block.state.BlockState -import ru.dbotthepony.mc.otm.capability.matter.IMatterTaskProvider import ru.dbotthepony.mc.otm.menu.MatterPanelMenu import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player @@ -12,10 +11,6 @@ import net.minecraftforge.common.util.LazyOptional import ru.dbotthepony.mc.otm.capability.MatteryCapability import java.util.HashMap import java.util.UUID -import ru.dbotthepony.mc.otm.capability.matter.MatterTask -import java.util.stream.Collectors -import ru.dbotthepony.mc.otm.capability.matter.MatterTaskAllocation -import ru.dbotthepony.mc.otm.capability.matter.PatternState import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.ListTag import net.minecraft.nbt.Tag @@ -23,17 +18,18 @@ import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.Level import net.minecraftforge.common.capabilities.Capability -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity +import ru.dbotthepony.mc.otm.capability.matter.* import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.registry.MBlockEntities import java.util.ArrayList -import java.util.List +import java.util.stream.Stream class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : - MatteryBlockEntity(MBlockEntities.MATTER_PANEL, p_155229_, p_155230_), IMatterGraphNode, IMatterTaskProvider { + MatteryBlockEntity(MBlockEntities.MATTER_PANEL, p_155229_, p_155230_), IMatterGraphNode, IReplicationTaskProvider { private val listeners = ArrayList() override val matterNode = Graph6Node(this) @@ -88,61 +84,59 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : matterNode.destroy(::MatterNetworkGraph) } - override fun getTaskHandler(): IMatterTaskProvider? { + override fun getTaskHandler(): IReplicationTaskProvider { return this } - private val _tasks = HashMap() + private val _tasks = HashMap() - override val tasks: Collection get() { - return _tasks.values.stream().filter { task: MatterTask? -> task!!.required() > 0 }.collect(Collectors.toList()) as Collection + override val replicationTasks: Stream get() { + return _tasks.values.stream().filter { it.required > 0 } } - override val allTasks: Collection get() { - return List.copyOf(_tasks.values) as Collection + override val allReplicationTasks: Stream get() { + return _tasks.values.stream() } - override fun allocateTask(simulate: Boolean): MatterTaskAllocation? { + override fun allocateTask(simulate: Boolean): ReplicationTaskAllocation? { val graph = matterNode.graph as MatterNetworkGraph? ?: return null for ((key, task) in _tasks) { if (task.required > 0) { - val getPattern = graph.getPattern(task.pattern!!) + val pattern = task.patternId?.let(graph::getPattern) ?: continue - if (getPattern != null) { - if (!simulate) { - val new = task.shrinkRequired(1) - _tasks[key] = new - listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(new) } - graph.onMatterTaskUpdated(new, task) - setChanged() - } - - return MatterTaskAllocation(task, getPattern) + if (!simulate) { + val new = task.allocate() + _tasks[key] = new + listeners.forEach { it.taskUpdated(new) } + graph.onMatterTaskUpdated(new, task) + setChanged() } + + return ReplicationTaskAllocation(task, pattern) } } return null } - override fun notifyTaskCompletion(task: MatterTask): Boolean { - var localTask = _tasks[task.id] ?: return false + override fun notifyTaskCompletion(taskId: UUID): Boolean { + var localTask = _tasks[taskId] ?: return false val oldTask = localTask - localTask = localTask.shrinkInProgress(1) + localTask = localTask.finish() val graph = matterNode.graph as MatterNetworkGraph? // Задача полностью выполнена - if (localTask.required <= 0 && localTask.in_progress <= 0) { - _tasks.remove(task.id) - graph?.onMatterTaskCreated(task) - listeners.forEach { menu: MatterPanelMenu -> menu.taskRemoved(localTask) } + if (localTask.required <= 0 && localTask.inProgress <= 0) { + _tasks.remove(taskId) + graph?.onMatterTaskFinished(localTask) + listeners.forEach { it.taskRemoved(localTask) } } else { // Задача обновлена - _tasks[task.id()] = localTask + _tasks[taskId] = localTask graph?.onMatterTaskUpdated(localTask, oldTask) - listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(localTask) } + listeners.forEach { it.taskUpdated(localTask) } } setChanged() @@ -155,7 +149,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : val list = ListTag() for (task in _tasks.values) { - list.add(task!!.serializeNBT()) + list.add(task.serializeNBT()) } nbt.put("tasks", list) @@ -167,16 +161,16 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : val list = nbt.getList("tasks", Tag.TAG_COMPOUND.toInt()) for (tag in list) { - val task = MatterTask.deserializeNBT(tag) + val task = ReplicationTask.deserializeNBT(tag) if (task != null) { - _tasks[task.id()] = task + _tasks[task.id] = task } } } - override fun getTask(id: UUID): MatterTask? { - return _tasks[id] + override fun getTask(id: UUID): ReplicationTask? { + return _tasks[id]?.asImmutable() } fun removeTask(id: UUID) { @@ -185,19 +179,17 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : (matterNode.graph as MatterNetworkGraph?)?.onMatterTaskRemoved(task) - listeners.forEach { menu: MatterPanelMenu -> menu.taskRemoved(task) } + listeners.forEach { it.taskRemoved(task) } setChanged() } - fun removeTask(state: PatternState) = removeTask(state.id) - - fun addTask(state: PatternState, how_much: Int): MatterTask { - val task = MatterTask(UUID.randomUUID(), state.id, state.item, 0, 0, how_much) - _tasks[task.id()] = task + fun addTask(state: IPatternState, count: Int): IReplicationTask<*> { + val task = ReplicationTask(UUID.randomUUID(), state.id, state.item, 0, 0, count) + _tasks[task.id] = task (matterNode.graph as MatterNetworkGraph?)?.onMatterTaskCreated(task) - listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(task) } + listeners.forEach { it.taskUpdated(task) } setChanged() return task diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt index 13c847970..286254d3a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt @@ -12,13 +12,10 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.items.CapabilityItemHandler -import ru.dbotthepony.mc.otm.TranslatableComponent -import ru.dbotthepony.mc.otm.block.entity.worker.MatteryWorkerBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJob -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJobStatus -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerTickContext +import ru.dbotthepony.mc.otm.core.TranslatableComponent +import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler @@ -30,26 +27,27 @@ import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph -import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.item.MatterDustItem +import ru.dbotthepony.mc.otm.core.map import ru.dbotthepony.mc.otm.menu.MatterRecyclerMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) - : MatteryWorkerBlockEntity(MBlockEntities.MATTER_RECYCLER, blockPos, blockState), IMatterGraphNode { + : MatteryWorkerBlockEntity(MBlockEntities.MATTER_RECYCLER, blockPos, blockState, ::Job), IMatterGraphNode { val matter = MatterHandlerImpl( - this::setChangedLight, + this::matterLevelUpdated, MatterDirection.EXTRACT, STORAGE ) - val container = MatteryContainer(this::setChangedLight, 1) + val container = MatteryContainer(this::itemContainerUpdated, 1) override val matterNode = Graph6Node(this) private var resolverNode = LazyOptional.of { this } private var valid = true - override val energy = WorkerEnergyStorage(this, MAX_POWER) + override val energy = WorkerEnergyStorage(this::powerLevelUpdated, MAX_POWER) override fun getMatterHandler(): IMatterHandler { return matter @@ -99,7 +97,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) override fun load(nbt: CompoundTag) { super.load(nbt) - nbt.ifHas("matter", CompoundTag::class.java, matter::deserializeNBT) + nbt.map("matter", matter::deserializeNBT) container.deserializeNBT(nbt["container"]) } @@ -107,15 +105,12 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) if (!valid) return super.getCapability(cap, side) - if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { - return itemHandler.get().cast() - } else if (cap === MatteryCapability.MATTER) { - return matter.get().cast() - } else if (cap === MatteryCapability.MATTER_NODE) { - return resolverNode.cast() + return when (cap) { + ForgeCapabilities.ITEM_HANDLER -> itemHandler.get().cast() + MatteryCapability.MATTER -> matter.get().cast() + MatteryCapability.MATTER_NODE -> resolverNode.cast() + else -> super.getCapability(cap, side) } - - return super.getCapability(cap, side) } override val defaultDisplayName: Component @@ -125,41 +120,39 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) return MatterRecyclerMenu(containerID, inventory, this) } - override fun onJobFinish(job: WorkerJob): WorkerJobStatus { + override fun onJobFinish(job: Job): Status { // вся логика в onWorkTick - return WorkerJobStatus() + return Status.SUCCESS } - override fun computeNextJob(): WorkerJob? { + override fun computeNextJob(): Pair { if (matter.missingMatter.isZero) - return null + return null to IdleReason.ITEM val stack = container[0] if (stack.isEmpty || stack.item !is MatterDustItem) { - return null + return null to IdleReason.ITEM } - val copy = stack.copy() - copy.count = 1 - - val dustMatter = (stack.item as MatterDustItem).getMatterValue(copy) ?: return null + val dustMatter = (stack.item as MatterDustItem).getMatterValue(stack.copy().also { it.count = 1 }) ?: return null to IdleReason.ITEM stack.shrink(1) - return WorkerJob(copy, dustMatter.value.toDouble() * MATTER_TICKS, POWER_CONSUMPTION) + container.setChanged(0) + return Job(dustMatter.value.toDouble() * MATTER_TICKS, POWER_CONSUMPTION) to null } - override fun onWorkTick(context: WorkerTickContext): WorkerJobStatus { + override fun onWorkTick(requiredPower: ImpreciseFraction, extractedPower: ImpreciseFraction, ticksAdvanced: Double): Status { if ((level?.random?.nextDouble() ?: 1.0) <= 0.4) - return WorkerJobStatus() + return Status.SUCCESS - val receive = if (context.ticksAdvanced == 1.0) MATTER_PER_TICK else MATTER_PER_TICK * context.ticksAdvanced + val receive = MATTER_PER_TICK * ticksAdvanced val received = matter.receiveMatterInner(receive, true) if (receive != received) - return WorkerJobStatus(false, 20) + return Status.FAILURE_MATTER matter.receiveMatterInner(receive, false) - return WorkerJobStatus() + return Status.SUCCESS } fun tick() { 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 bdcdc5286..125d88ee8 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 @@ -8,49 +8,93 @@ import net.minecraft.server.level.ServerLevel 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.Level import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.items.CapabilityItemHandler -import ru.dbotthepony.mc.otm.TranslatableComponent -import ru.dbotthepony.mc.otm.block.entity.worker.MatteryWorkerBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJob -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJobStatus -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerTickContext +import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.* import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainerFilterOnlyOut -import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph -import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.matter.baselineComplexityReplicateTicks import ru.dbotthepony.mc.otm.matter.getMatterValue import ru.dbotthepony.mc.otm.menu.MatterReplicatorMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.* class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : - MatteryWorkerBlockEntity(MBlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_), IMatterGraphNode { + MatteryWorkerBlockEntity(MBlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_, { + try { + ReplicatorJob(it) + } catch(err: NoSuchElementException) { + null + } + }), IMatterGraphNode { - override val energy = WorkerEnergyStorage(this, STORAGE, MAX_IO) + class ReplicatorJob : ItemJob { + val matterPerTick: ImpreciseFraction + val task: ReplicationTask + var matterValue: ImpreciseFraction + val pattern: PatternState? + val asDust: Boolean + + constructor(tag: CompoundTag) : super(tag) { + matterPerTick = tag.getImpreciseFraction("matterPerTick") + matterValue = tag.getImpreciseFraction("matterValue") + pattern = tag.map("pattern", PatternState::deserializeNBT) + asDust = tag.getBoolean("asDust") + task = tag.map("task", ReplicationTask::deserializeNBT) ?: throw NoSuchElementException("Unable to deserialize matter task") + } + + constructor( + itemStack: ItemStack, + matterPerTick: ImpreciseFraction, + task: ReplicationTask, + matterValue: ImpreciseFraction, + pattern: PatternState?, + asDust: Boolean, + ticks: Double, + ) : super(itemStack, ticks, BASE_CONSUMPTION) { + this.matterPerTick = matterPerTick + this.task = task + this.matterValue = matterValue + this.pattern = pattern + this.asDust = asDust + } + + override fun serializeNBT(): CompoundTag { + return super.serializeNBT().also { + it["matterPerTick"] = this.matterPerTick + it["task"] = this.task.serializeNBT() + it["matterValue"] = this.matterValue + + if (this.pattern != null) + it["pattern"] = this.pattern.serializeNBT() + + it["asDust"] = this.asDust + } + } + } + + override val energy = WorkerEnergyStorage(this::powerLevelUpdated, STORAGE, MAX_IO) override val matterNode = Graph6Node(this) private val resolverNode = LazyOptional.of { this } - @JvmField val matter = MatterHandlerImpl( - this::setChangedLight, + this::matterLevelUpdated, MatterDirection.RECEIVE, ImpreciseFraction(2) ) - // обычные запросы - @JvmField - val container = MatteryContainer(this::setChangedLight, 5) + val container = MatteryContainer(this::itemContainerUpdated, 5) private val itemHandler = container.handler(MatteryContainerFilterOnlyOut) override val defaultDisplayName: Component @@ -60,38 +104,42 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : return MatterReplicatorMenu(containerID, inventory, this) } - override fun onJobFinish(job: WorkerJob): WorkerJobStatus { - if (job.data.getBoolean("as_dust")) { - val matterValue = moveMatterAsDustIntoContainer(ImpreciseFraction.deserializeNBT(job["matter"]), container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING) + override fun onJobFinish(job: ReplicatorJob): Status { + if (job.asDust) { + job.matterValue = moveMatterAsDustIntoContainer(job.matterValue, container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING) - if (!matterValue.isZero) { - job["matter"] = matterValue.serializeNBT() - return WorkerJobStatus(false, 20) + if (!job.matterValue.isZero) { + return Status.FAILURE_WAIT } - (matterNode.graph as MatterNetworkGraph?)?.notifyTaskCompletion(MatterTask.deserializeNBT(job["task"])!!) - - return WorkerJobStatus() + (matterNode.graph as MatterNetworkGraph?)?.notifyTaskCompletion(job.task.id) + return Status.SUCCESS } - if (!container.fullyAddItem(job.stack, FIRST_ACTUAL_OUTPUT_SLOT .. LAST_ACTUAL_OUTPUT_SLOT)) { - return WorkerJobStatus(false, 20) + if (!container.fullyAddItem(job.itemStack, FIRST_ACTUAL_OUTPUT_SLOT .. LAST_ACTUAL_OUTPUT_SLOT)) { + return Status.FAILURE_ITEM } - (matterNode.graph as MatterNetworkGraph?)?.notifyTaskCompletion(MatterTask.deserializeNBT(job["task"])!!) - return WorkerJobStatus() + (matterNode.graph as MatterNetworkGraph?)?.notifyTaskCompletion(job.task.id) + return Status.SUCCESS } - override fun onMatterTaskCreated(task: MatterTask) { - isIdling = false + override fun onMatterTaskCreated(task: IReplicationTask<*>) { + if (idleReason == IdleReason.OBSERVING) { + isIdling = false + } } - override fun onMatterTaskUpdated(new_state: MatterTask, old_state: MatterTask) { - isIdling = false + override fun > onMatterTaskUpdated(newState: T, oldState: T) { + if (idleReason == IdleReason.OBSERVING) { + isIdling = false + } } - override fun onPatternAdded(state: PatternState) { - isIdling = false + override fun onPatternAdded(state: IPatternState) { + if (idleReason == IdleReason.OBSERVING) { + isIdling = false + } } override fun setRemoved() { @@ -106,33 +154,35 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatterNetworkGraph.discoverFull(this, matterNode) } - override fun computeNextJob(): WorkerJob? { - val graph = matterNode.graph as MatterNetworkGraph? ?: return null - val allocation = graph.allocateTask(false) ?: return null + override fun computeNextJob(): Pair { + if (energy.batteryLevel < BASE_CONSUMPTION) { + return null to IdleReason.POWER + } + + val graph = matterNode.graph as MatterNetworkGraph? ?: return null to null + val allocation = graph.allocateTask(simulate = false) ?: return null to IdleReason.OBSERVING val stack = allocation.task.stack(1) val matter = getMatterValue(stack) // ???????? - if (matter.isZero) return null + if (matter.isZero) return null to null val ticks = matter.complexity * baselineComplexityReplicateTicks - return WorkerJob(stack, ticks, BASE_CONSUMPTION, CompoundTag().also { - it["matter_per_tick"] = (matter.value / ticks).serializeNBT() - it["task"] = allocation.task.serializeNBT() - it["matter"] = matter.value.serializeNBT() - - if (allocation.pattern != null) - it["pattern"] = allocation.pattern.serializeNBT() - - if ((level?.random?.nextDouble() ?: 1.0) > (allocation.pattern?.research ?: 2.0)) - it["as_dust"] = true - }) + return ReplicatorJob( + itemStack = stack, + matterPerTick = matter.value / ticks, + task = allocation.task.asImmutable(), + matterValue = matter.value, + pattern = allocation.pattern?.asImmutable(), + asDust = (level?.random?.nextDouble() ?: 1.0) > (allocation.pattern?.researchPercent ?: 2.0), + ticks = ticks, + ) to null } - override fun onWorkTick(context: WorkerTickContext): WorkerJobStatus { - val drainPerTick = ImpreciseFraction.deserializeNBT(context.job.data["matter_per_tick"]) - val graph = matterNode.graph as MatterNetworkGraph? ?: return WorkerJobStatus(false, 20) + override fun onWorkTick(requiredPower: ImpreciseFraction, extractedPower: ImpreciseFraction, ticksAdvanced: Double): Status { + val drainPerTick = currentJob!!.matterPerTick * ticksAdvanced + val graph = matterNode.graph as MatterNetworkGraph? ?: return Status.FAILURE_WAIT_FAST if (matter.extractMatterInner(drainPerTick, true) < drainPerTick) { // в машине недостаточно материи @@ -142,44 +192,42 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : val toExtract = drainPerTick - matter.extractMatterInner(drainPerTick, true) val drain = graph.extractMatter(toExtract, true) - if (drain < toExtract) { + if (drain != toExtract) { // недостаточно материи в сети - return WorkerJobStatus(false, 200) + return Status.FAILURE_MATTER } // достаточно материи в сети + внутри машины matter.extractMatterInner(drainPerTick, false) graph.extractMatter(drain, false) - return WorkerJobStatus() + return Status.SUCCESS } else { // в тик требуется меньше материи, чем её может хранить репликатор // примем из сети недостающее количество бака материи, или 200 тиков репликации, что меньше - val toExtract = - matter.missingMatter.coerceAtMost(drainPerTick.times(DRAIN_MULT)) - - val drain = graph.extractMatter(toExtract, true) + val drain = graph.extractMatter(matter.missingMatter.coerceAtMost(drainPerTick * DRAIN_MULT), true) if (drain.isZero) { // в сети нет материи - return WorkerJobStatus(false, 200) + return Status.FAILURE_MATTER } val received = matter.receiveMatterOuter(drain, false) graph.extractMatter(received, false) // получили материю, проверяем возможность работы - if (matter.extractMatterInner(drainPerTick, false) >= drainPerTick) { - return WorkerJobStatus() + if (matter.extractMatterInner(drainPerTick, true) >= drainPerTick) { + matter.extractMatterInner(drainPerTick, false) + return Status.SUCCESS } else { // :( - return WorkerJobStatus(false, 200) + return Status.FAILURE_WAIT } } } // в машине достаточно материи matter.extractMatterInner(drainPerTick, false) - return WorkerJobStatus() + return Status.SUCCESS } override fun saveAdditional(nbt: CompoundTag) { @@ -191,10 +239,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : override fun load(nbt: CompoundTag) { super.load(nbt) container.deserializeNBT(nbt["container"]) - - nbt.ifHas("matter", CompoundTag::class.java) { - matter.deserializeNBT(it) - } + nbt.map("matter", matter::deserializeNBT) } private var valid = true @@ -213,8 +258,8 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : override fun getCapability(cap: Capability, side: Direction?): LazyOptional { if (valid) { - if (cap === MatteryCapability.MATTER_NODE) return resolverNode.cast() - if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return itemHandler.get().cast() + if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast() + if (cap == ForgeCapabilities.ITEM_HANDLER) return itemHandler.get().cast() } return super.getCapability(cap, side) 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 020e67d48..a604d99c4 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 @@ -12,16 +12,16 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.items.CapabilityItemHandler -import ru.dbotthepony.mc.otm.TranslatableComponent -import ru.dbotthepony.mc.otm.block.entity.worker.MatteryWorkerBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJob -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJobStatus +import ru.dbotthepony.mc.otm.core.TranslatableComponent +import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage +import ru.dbotthepony.mc.otm.capability.matter.IPatternState import ru.dbotthepony.mc.otm.capability.matter.PatternState import ru.dbotthepony.mc.otm.container.MatteryContainer +import ru.dbotthepony.mc.otm.container.MatteryContainerFilter import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode @@ -32,26 +32,38 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities import java.util.* class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : - MatteryWorkerBlockEntity(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_), IMatterGraphNode { + MatteryWorkerBlockEntity(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ::ItemJob), IMatterGraphNode { - val container = MatteryContainer(this::setChanged, 1) - override val energy = WorkerEnergyStorage(this, STORAGE, MAX_IO) - private val itemHandler = container.handler( - { _: Int, stack: ItemStack -> canDecompose(stack) }, - { _: Int, _: Int, _: ItemStack -> isIdling } - ) + val container = MatteryContainer(this::itemContainerUpdated, 1) + override val energy = WorkerEnergyStorage(this::powerLevelUpdated, STORAGE, MAX_IO) + + private val itemHandler = container.handler(object : MatteryContainerFilter { + override fun canInsert(slot: Int, stack: ItemStack): Boolean { + return canDecompose(stack) + } + + override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean { + return isIdling + } + }) // IMatterGraphNode - override fun onPatternAdded(state: PatternState) { - isIdling = false + override fun onPatternAdded(state: IPatternState) { + if (idleReason == IdleReason.OBSERVING) { + isIdling = false + } } - override fun onPatternRemoved(state: PatternState) { - isIdling = false + override fun onPatternRemoved(state: IPatternState) { + if (idleReason == IdleReason.OBSERVING) { + isIdling = false + } } - override fun onPatternUpdated(new_state: PatternState, old_state: PatternState) { - isIdling = false + override fun onPatternUpdated(newState: IPatternState, oldState: IPatternState) { + if (idleReason == IdleReason.OBSERVING) { + isIdling = false + } } // /IMatterGraphNode @@ -61,7 +73,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : override fun getCapability(cap: Capability, side: Direction?): LazyOptional { if (valid) { - if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return itemHandler.get().cast() + if (cap == ForgeCapabilities.ITEM_HANDLER) return itemHandler.get().cast() if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast() } @@ -105,72 +117,71 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : super.load(nbt) } - override fun onJobFinish(job: WorkerJob): WorkerJobStatus { - val grid = matterNode.graph as MatterNetworkGraph? ?: return WorkerJobStatus(false, 100) + override fun onJobFinish(job: ItemJob): Status { + val grid = matterNode.graph as MatterNetworkGraph? ?: return Status.FAILURE_WAIT - val stack = job.stack - if (stack.isEmpty || !hasMatterValue(stack)) return WorkerJobStatus() + val stack = job.itemStack + if (stack.isEmpty || !hasMatterValue(stack)) return Status.SUCCESS - val getState = grid.findPatterns(stack.item) - var findState: PatternState? = null + var findState: IPatternState? = null - for (state in getState) { - if (state.item() === stack.item) { - if (findState == null && state.research() < 1.0) { - findState = state - } else if (findState != null && findState.research() < state.research()) { - findState = state - } + for (state in grid.patterns.filter { it.item === stack.item }) { + if (findState == null && state.researchPercent < 1.0) { + findState = state + } else if (findState != null && findState.researchPercent < state.researchPercent) { + findState = state } } val new = if (findState != null) { - PatternState(findState.id(), stack.item, findState.research() + 0.2) + PatternState(findState.id, stack.item, findState.researchPercent + 0.2) } else { PatternState(UUID.randomUUID(), stack.item, 0.2) } if (!grid.insertPattern(new, onlyUpdate = false, simulate = false).isFailed) { - return WorkerJobStatus() + return Status.SUCCESS } else { - return WorkerJobStatus(false, 200) + return Status.FAILURE_WAIT } } - override fun computeNextJob(): WorkerJob? { - val grid = matterNode.graph as MatterNetworkGraph? ?: return null + override fun computeNextJob(): Pair { + if (energy.batteryLevel.isZero) { + return null to IdleReason.POWER + } + + val grid = matterNode.graph as MatterNetworkGraph? ?: return null to null val stack = container.getItem(0) - if (stack.isEmpty || !canDecompose(stack)) return null + if (stack.isEmpty || !canDecompose(stack)) return null to IdleReason.ITEM - val getState = grid.findPatterns(stack.item) - var findState: PatternState? = null + var findState: IPatternState? = null - for (state in getState) { - if (state.item === stack.item && state.research < 1.0) { + for (state in grid.patterns.filter { it.item === stack.item }) { + if (state.researchPercent < 1.0) { findState = state - } else if (state.item === stack.item && state.research >= 1.0) { - return null + } else if (state.researchPercent >= 1.0) { + return null to IdleReason.ITEM } } - val new: PatternState = + val new: IPatternState = if (findState != null) { - PatternState(findState.id, stack.item, findState.research + 0.2) + PatternState(findState.id, stack.item, findState.researchPercent + 0.2) } else { PatternState(UUID.randomUUID(), stack.item, 0.2) } if (!grid.insertPattern(new, onlyUpdate = false, simulate = true).isFailed) { - val copy = stack.copy() - copy.count = 1 + val copy = stack.copy().also { it.count = 1 } stack.shrink(1) container.setChanged() - return WorkerJob(copy, getMatterValue(copy).complexity * baselineComplexityScanTicks, BASE_CONSUMPTION) + return ItemJob(copy, getMatterValue(copy).complexity * baselineComplexityScanTicks, BASE_CONSUMPTION) to null } - return null + return null to IdleReason.ITEM } override fun setLevel(p_155231_: Level) { 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 2e2e46026..eafe1d9d7 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 @@ -13,16 +13,17 @@ import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.util.LazyOptional -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.ifHas +import ru.dbotthepony.mc.otm.core.ifHas import ru.dbotthepony.mc.otm.menu.DriveRackMenu -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.storage.* diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveViewerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveViewerBlockEntity.kt index eb83c3295..015fac0e0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveViewerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveViewerBlockEntity.kt @@ -11,16 +11,17 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.state.BlockState import ru.dbotthepony.mc.otm.OverdriveThatMatters -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.block.storage.DriveViewerBlock -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.menu.DriveViewerMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set import javax.annotation.ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt index 4aefec61e..b7137365c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt @@ -26,26 +26,26 @@ import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.network.NetworkEvent import org.apache.logging.log4j.LogManager -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.container.MatteryContainer -import ru.dbotthepony.mc.otm.get +import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph -import ru.dbotthepony.mc.otm.ifHas +import ru.dbotthepony.mc.otm.core.ifHas import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.storage.* import java.math.BigInteger import java.util.* import java.util.function.Supplier import kotlin.collections.HashMap -import kotlin.collections.HashSet class ItemMonitorPlayerSettings : INBTSerializable, MatteryPacket { enum class RefillSource(val component: Component) { @@ -296,6 +296,7 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : override fun stillValid(p_18946_: Player) = true override fun getItem(p_18941_: Int): ItemStack { + require(p_18941_ == 1) { "Invalid slot ID: $p_18941_" } return craftingRecipe?.resultItem?.copy() ?: ItemStack.EMPTY } @@ -423,12 +424,13 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } override fun removeItemNoUpdate(p_18951_: Int): ItemStack { - // return removeItem(p_18951_, craftingRecipe?.resultItem?.count ?: Int.MAX_VALUE) throw UnsupportedOperationException() } override fun setItem(p_18944_: Int, p_18945_: ItemStack) { - throw UnsupportedOperationException() + if ((craftingRecipe != null && !craftingRecipe!!.resultItem.isEmpty) || !p_18945_.isEmpty) { + throw RuntimeException("BUG-DETECT: Tried to set crafting result slot item to something, and either we have crafting recipe which have valid result, or we are trying to set slot to non empty item: $p_18945_") + } } override fun setChanged() {} 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 e073ba5da..1ba36b88d 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 @@ -25,10 +25,7 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.container.ItemFilter -import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.core.isPositive -import ru.dbotthepony.mc.otm.core.isZero -import ru.dbotthepony.mc.otm.core.plus +import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.GraphNodeListener import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt index 729105d70..a2a63c5ff 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt @@ -23,8 +23,7 @@ import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.container.ItemFilter -import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.core.plus +import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.GraphNodeListener import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt index 5194289da..499b66901 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt @@ -13,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.util.LazyOptional import ru.dbotthepony.mc.otm.OverdriveThatMatters -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage @@ -24,7 +24,8 @@ import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph import ru.dbotthepony.mc.otm.menu.StoragePowerSupplierMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MNames -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.STORAGE_POWER_SUPPLIER, blockPos, blockState) { override val defaultDisplayName: Component diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/worker/MatteryWorkerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/worker/MatteryWorkerBlockEntity.kt deleted file mode 100644 index bb3991c28..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/worker/MatteryWorkerBlockEntity.kt +++ /dev/null @@ -1,261 +0,0 @@ -package ru.dbotthepony.mc.otm.block.entity.worker - -import net.minecraft.world.level.block.entity.BlockEntityType -import net.minecraft.core.BlockPos -import net.minecraft.world.level.block.state.BlockState -import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity -import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.DoubleTag -import net.minecraft.world.level.block.Block -import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.core.weakGreaterOrEqual -import ru.dbotthepony.mc.otm.core.weakLessThan -import ru.dbotthepony.mc.otm.ifHas -import ru.dbotthepony.mc.otm.set - -abstract class MatteryWorkerBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : - MatteryPoweredBlockEntity(p_155228_, p_155229_, p_155230_) { - var workTicks = 0.0 - protected set - - var throttleTicks = 0 - protected set - - var currentJob: WorkerJob? = null - protected set - - // если isIdling То ничего не делать - // isIdling должна быть выставлена в true если что то изменилось, что могло создать работу - var isIdling = false - protected set - - val isUnableToProcess: Boolean get() = throttleTicks > 0 - - val workProgress: Float - get() { - val currentJob = currentJob ?: return 0.0f - return (workTicks / currentJob.ticks).coerceAtMost(1.0).toFloat() - } - - override fun saveAdditional(nbt: CompoundTag) { - super.saveAdditional(nbt) - nbt["work_ticks"] = workTicks - currentJob?.let { nbt["current_job"] = it.serializeNBT() } - } - - override fun load(nbt: CompoundTag) { - super.load(nbt) - - nbt.ifHas("work_ticks", DoubleTag::class.java) { - workTicks = it.asDouble - } - - currentJob = WorkerJob.deserializeNBT(nbt["current_job"]) - - if (currentJob == null) - workTicks = 0.0 - } - - override fun setChanged() { - super.setChanged() - isIdling = false - } - - override fun setChangedLight() { - super.setChangedLight() - isIdling = false - } - - /** - * @param job current job - * @return whenever machine can finish it's job. return false if machine for whatever reason can't finish it's job, - * waiting on conditions to be met - */ - protected abstract fun onJobFinish(job: WorkerJob): WorkerJobStatus - - /** - * @param context context for current job - * @return whenever machine can perform it - */ - protected open fun onWorkTick(context: WorkerTickContext): WorkerJobStatus { - return WorkerJobStatus() - } - - private var idleTicksAnim = 0 - private var workingTicksAnim = 0 - private var errorTicksAnim = 0 - - override fun redstoneStatusUpdated(new_blocked: Boolean, old_blocked: Boolean) { - super.redstoneStatusUpdated(new_blocked, old_blocked) - isIdling = new_blocked - } - - protected fun workerLoop() { - if (errorTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.ERROR) { - level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.ERROR), Block.UPDATE_CLIENTS) - } - - if (throttleTicks > 0) { - workingTicksAnim = 0 - idleTicksAnim = 0 - throttleTicks-- - errorTicksAnim++ - - if (throttleTicks > 0) - return - } - - if (isIdling) { - workingTicksAnim = 0 - errorTicksAnim = 0 - idleTicksAnim++ - - if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.IDLE) { - level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS) - } - - return - } - - var currentJob = currentJob - - if (currentJob == null) { - if (isBlockedByRedstone) { - isIdling = true - return - } - - val input = computeNextJob() - - if (input == null) { - isIdling = true - workingTicksAnim = 0 - return - } - - this.currentJob = input - currentJob = input - } - - if (isBlockedByRedstone) { - isIdling = true - return - } - - if (!currentJob.power.isZero && energy.batteryLevel.isZero) { - idleTicksAnim++ - - if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.IDLE) { - level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS) - } - - return - } - - idleTicksAnim = 0 - - if (weakLessThan(workTicks, currentJob.ticks)) { - if (!currentJob.power.isZero) { - // сколько осталось тиков работать - val ticksLeft = currentJob.ticks - workTicks - val requiredPower: ImpreciseFraction - - // запрос энергии на то количество, сколько действительно осталось работать - if (ticksLeft > 1.0) { - requiredPower = currentJob.power - } else { - requiredPower = currentJob.power * ticksLeft - } - - val extractedPower = if (requiredPower.isZero) ImpreciseFraction.ZERO else energy.extractEnergyInner(requiredPower, true) - - // сколько тиков мы "проработали" - // может быть меньше, чем единица, если недостаточно питания или мы завершаем работу, - // для которой осталось дробное количество тиков - val ticksAdvanced = (extractedPower / requiredPower).toDouble().coerceAtMost(ticksLeft) - val ticksAdvancedWeak = if (requiredPower.isZero) 1.0 else ticksAdvanced - val status = onWorkTick(WorkerTickContext(currentJob, requiredPower, extractedPower, ticksAdvanced)) - - if (!status.valid) { - throttleTicks += status.throttle - return - } - - workingTicksAnim++ - errorTicksAnim = 0 - - val updatedWorkTicks = (workTicks + ticksAdvancedWeak).coerceAtMost(currentJob.ticks) - - if (weakGreaterOrEqual(updatedWorkTicks, currentJob.ticks)) { - workTicks = currentJob.ticks - energy.extractEnergyInner(extractedPower * (1.0 - (updatedWorkTicks - currentJob.ticks)), false) - - val finish = onJobFinish(currentJob) - - if (finish.valid) { - this.currentJob = null - workTicks = 0.0 - } else { - throttleTicks += finish.throttle - } - } else { - workTicks = updatedWorkTicks - energy.extractEnergyInner(extractedPower, false) - } - } else { - val ticksLeft = (currentJob.ticks - workTicks).coerceAtMost(1.0) - val status = onWorkTick(WorkerTickContext(currentJob, ImpreciseFraction.ZERO, ImpreciseFraction.ZERO, ticksLeft)) - - if (!status.valid) { - throttleTicks += status.throttle - return - } - - workingTicksAnim++ - errorTicksAnim = 0 - workTicks = (workTicks + 1.0).coerceAtMost(currentJob.ticks) - - if (weakGreaterOrEqual(workTicks, currentJob.ticks)) { - val finish = onJobFinish(currentJob) - - if (finish.valid) { - this.currentJob = null - workTicks = 0.0 - } else { - throttleTicks += finish.throttle - } - } - } - } else { - val finish = onJobFinish(currentJob) - - if (finish.valid) { - this.currentJob = null - workTicks = 0.0 - errorTicksAnim = 0 - } else { - throttleTicks += finish.throttle - errorTicksAnim++ - } - } - - if (workingTicksAnim > 20 && - errorTicksAnim == 0 && - blockState.hasProperty(WorkerState.WORKER_STATE) && - blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.WORKING) - { - level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS) - } - } - - /** - * Determine which item can be processed from input slots if idling - * @return any item in input slots. null if no work is available - */ - protected abstract fun computeNextJob(): WorkerJob? - - fun basicTicker() { - batteryChargeLoop() - workerLoop() - } -} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/worker/WorkerLogic.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/worker/WorkerLogic.kt deleted file mode 100644 index 87c73438d..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/worker/WorkerLogic.kt +++ /dev/null @@ -1,85 +0,0 @@ -package ru.dbotthepony.mc.otm.block.entity.worker - -import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.DoubleTag -import net.minecraft.nbt.Tag -import net.minecraft.util.StringRepresentable -import net.minecraft.world.item.ItemStack -import net.minecraft.world.level.block.state.properties.EnumProperty -import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.set - -@JvmRecord -data class WorkerTickContext( - val job: WorkerJob, - val requiredPower: ImpreciseFraction, - val extractedPower: ImpreciseFraction, - val ticksAdvanced: Double -) - -enum class WorkerState : StringRepresentable { - IDLE, - WORKING, - ERROR; - - companion object { - @JvmField - val WORKER_STATE: EnumProperty = EnumProperty.create("worker", WorkerState::class.java) - @JvmField - val SEMI_WORKER_STATE: EnumProperty = EnumProperty.create("worker", WorkerState::class.java, IDLE, WORKING) - } - - override fun getSerializedName(): String { - return if (this == IDLE) "idle" else if (this == WORKING) "working" else "error" - } -} - -@JvmRecord -data class WorkerJobStatus @JvmOverloads constructor(val valid: Boolean = true, val throttle: Int = 0) { - constructor(throttle: Int) : this(false, throttle) -} - -@JvmRecord -data class WorkerJob @JvmOverloads constructor( - val stack: ItemStack, - val ticks: Double, - val power: ImpreciseFraction = ImpreciseFraction.ZERO, - val data: CompoundTag = CompoundTag()) { - - fun serializeNBT(): CompoundTag { - return CompoundTag().also { - it["stack"] = stack.serializeNBT() - it["ticks"] = ticks - it["power"] = power.serializeNBT() - it["data"] = data - } - } - - operator fun get(index: String) = data[index] - operator fun set(index: String, value: Tag) { data[index] = value } - operator fun set(index: String, value: Int) { data[index] = value } - operator fun set(index: String, value: Byte) { data[index] = value } - operator fun set(index: String, value: Short) { data[index] = value } - operator fun set(index: String, value: Long) { data[index] = value } - operator fun set(index: String, value: Float) { data[index] = value } - operator fun set(index: String, value: Double) { data[index] = value } - operator fun set(index: String, value: String) { data[index] = value } - operator fun set(index: String, value: Boolean) { data[index] = value } - operator fun set(index: String, value: ByteArray) { data[index] = value } - operator fun set(index: String, value: IntArray) { data[index] = value } - operator fun set(index: String, value: LongArray) { data[index] = value } - - companion object { - @JvmStatic - fun deserializeNBT(tag: Tag?): WorkerJob? { - val nbt = tag as? CompoundTag ?: return null - - return WorkerJob( - ItemStack.of(nbt["stack"] as? CompoundTag ?: return null), - (nbt["ticks"] as? DoubleTag ?: return null).asDouble, - ImpreciseFraction.deserializeNBT(nbt["power"]), - nbt["data"] as? CompoundTag ?: return null - ) - } - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterBottlerBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterBottlerBlock.kt index 3ce941a6b..e6542499d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterBottlerBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterBottlerBlock.kt @@ -19,7 +19,7 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterDecomposerBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterDecomposerBlock.kt index 992109b78..faf3065c4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterDecomposerBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterDecomposerBlock.kt @@ -17,7 +17,7 @@ import net.minecraft.world.level.block.Block import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterRecyclerBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterRecyclerBlock.kt index 276657139..d8c99395a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterRecyclerBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterRecyclerBlock.kt @@ -15,7 +15,7 @@ import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.matter.MatterRecyclerBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterReplicatorBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterReplicatorBlock.kt index 9d3fed1d3..1d15fbbc6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterReplicatorBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterReplicatorBlock.kt @@ -15,7 +15,7 @@ import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.matter.MatterReplicatorBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterScannerBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterScannerBlock.kt index f58763a77..51b3a72c3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterScannerBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/matter/MatterScannerBlock.kt @@ -15,7 +15,7 @@ import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.matter.MatterScannerBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/DriveViewerBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/DriveViewerBlock.kt index a3a815d1c..f0776f5b8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/DriveViewerBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/DriveViewerBlock.kt @@ -17,7 +17,7 @@ import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.VoxelShape import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.storage.DriveViewerBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageBusBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageBusBlock.kt index f9fae0cf3..baf657dbf 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageBusBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageBusBlock.kt @@ -22,7 +22,7 @@ import ru.dbotthepony.mc.otm.block.StorageCableBlock import ru.dbotthepony.mc.otm.block.entity.storage.StorageBusBlockEntity import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes -import ru.dbotthepony.mc.otm.unaryMinus +import ru.dbotthepony.mc.otm.core.unaryMinus class StorageBusBlock : RotatableMatteryBlock(), EntityBlock { override val hasFreeRotation: Boolean get() = true diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt index 62196cf8b..35a169791 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt @@ -23,7 +23,7 @@ import ru.dbotthepony.mc.otm.block.entity.storage.StorageExporterBlockEntity import ru.dbotthepony.mc.otm.block.entity.storage.StorageImporterBlockEntity import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.shapes.BlockShapes -import ru.dbotthepony.mc.otm.unaryMinus +import ru.dbotthepony.mc.otm.core.unaryMinus class StorageImporterBlock : RotatableMatteryBlock(), EntityBlock { override val hasFreeRotation: Boolean get() = true diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/EnergyStorageImpl.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/EnergyStorageImpl.kt index d8c4d90a4..444d78bce 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/EnergyStorageImpl.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/EnergyStorageImpl.kt @@ -12,12 +12,12 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.capabilities.ICapabilityProvider import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.energy.CapabilityEnergy import ru.dbotthepony.mc.otm.compat.mekanism.MatteryToMekanismEnergyWrapper import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.ifHas -import ru.dbotthepony.mc.otm.set -import ru.dbotthepony.mc.otm.tagNotNull +import ru.dbotthepony.mc.otm.core.ifHas +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set +import ru.dbotthepony.mc.otm.core.tagNotNull private enum class EnergyFlow { INPUT, OUTPUT, BI_DIRECTIONAL @@ -47,9 +47,9 @@ sealed class ItemEnergyStorageImpl( protected set override var batteryLevel: ImpreciseFraction - get() = itemStack.tag?.get("energy")?.let { ImpreciseFraction.deserializeNBT(it) } ?: ImpreciseFraction.ZERO + get() = itemStack.tag?.get(NBT_KEY)?.let { ImpreciseFraction.deserializeNBT(it) } ?: ImpreciseFraction.ZERO protected set(value) { - itemStack.tagNotNull.put("energy", value.serializeNBT()) + itemStack.tagNotNull.put(NBT_KEY, value.serializeNBT()) } override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { @@ -127,6 +127,10 @@ sealed class ItemEnergyStorageImpl( override fun canReceive(): Boolean { return type != EnergyFlow.OUTPUT } + + companion object { + const val NBT_KEY = "energy" + } } open class EnergyConsumerItem(stack: ItemStack, maxBatteryLevel: ImpreciseFraction, maxInput: ImpreciseFraction? = null, maxOutput: ImpreciseFraction? = maxInput) 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 3207d6527..49f341a1f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt @@ -1,7 +1,8 @@ package ru.dbotthepony.mc.otm.capability import net.minecraft.core.Direction -import net.minecraft.world.entity.LivingEntity +import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.ItemStack import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.capabilities.ICapabilityProvider import net.minecraftforge.common.util.LazyOptional @@ -9,8 +10,10 @@ import net.minecraftforge.energy.IEnergyStorage import net.minecraftforge.fml.ModList import ru.dbotthepony.mc.otm.compat.mekanism.getMekanismEnergySided import ru.dbotthepony.mc.otm.compat.mekanism.mekanismEnergy +import ru.dbotthepony.mc.otm.container.iterator +import ru.dbotthepony.mc.otm.core.iterator import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.orNull +import ru.dbotthepony.mc.otm.core.orNull val ICapabilityProvider.matteryPlayer: MatteryPlayerCapability? get() = getCapability(MatteryCapability.MATTERY_PLAYER).orNull() @@ -117,3 +120,58 @@ fun ICapabilityProvider.getMatteryEnergySided(side: Direction? = null): LazyOpti return getCapability(MatteryCapability.ENERGY, side) } + +fun Player.extendedItemIterator(): MutableIterator { + return object : MutableIterator { + private val regular = this@extendedItemIterator.inventory.iterator() + private val mattery: MutableIterator + private var isSecond = false + + init { + val get = this@extendedItemIterator.matteryPlayer + + if (get != null && get.hasExoSuit) { + mattery = get.exoSuitContainer.iterator() + } else { + mattery = object : MutableIterator { + override fun hasNext(): Boolean { + return false + } + + override fun next(): ItemStack { + throw UnsupportedOperationException() + } + + override fun remove() { + throw UnsupportedOperationException() + } + } + } + } + + override fun hasNext(): Boolean { + return regular.hasNext() || mattery.hasNext() + } + + override fun next(): ItemStack { + if (isSecond) { + return mattery.next() + } + + if (!regular.hasNext()) { + isSecond = true + return mattery.next() + } + + return regular.next() + } + + override fun remove() { + if (isSecond) { + mattery.remove() + } else { + regular.remove() + } + } + } +} 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 2de4a936d..187635978 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.capability import it.unimi.dsi.fastutil.objects.ObjectArraySet import net.minecraft.ChatFormatting -import net.minecraft.advancements.CriteriaTriggers import net.minecraft.core.Direction import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.ListTag @@ -39,7 +38,7 @@ import ru.dbotthepony.mc.otm.android.AndroidFeatureType import ru.dbotthepony.mc.otm.android.AndroidResearch import ru.dbotthepony.mc.otm.android.AndroidResearchType import ru.dbotthepony.mc.otm.container.MatteryContainer -import ru.dbotthepony.mc.otm.core.ImpreciseFraction +import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.menu.ExoSuitInventoryMenu import ru.dbotthepony.mc.otm.network.* import ru.dbotthepony.mc.otm.registry.AndroidFeatures @@ -79,6 +78,10 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn private set(value) { _exoSuitMenu = null + if (ply.containerMenu.slots.any { it.container == field }) { + ply.closeContainer() + } + for (i in 0 until value.containerSize.coerceAtMost(field.containerSize)) { if (!field[i].isEmpty) { value[i] = field[i] @@ -627,7 +630,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn shouldSendIteration = false } - if (hasExoSuit && ply.containerMenu != exoSuitMenu) { + if (hasExoSuit && ply.containerMenu == ply.inventoryMenu) { exoSuitMenu.broadcastChanges() } @@ -762,10 +765,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn @Suppress("unused") companion object { - @JvmField val UNAFFECTED_EFFECTS = ObjectArraySet() - @JvmStatic fun registerEffects(event: FMLCommonSetupEvent) { UNAFFECTED_EFFECTS.add(MobEffects.CONDUIT_POWER) UNAFFECTED_EFFECTS.add(MobEffects.HEAL) @@ -782,7 +783,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn UNAFFECTED_EFFECTS.add(MobEffects.DOLPHINS_GRACE) } - @SubscribeEvent fun onLivingTick(event: LivingTickEvent) { val ent = event.entity @@ -797,7 +797,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn } } - @SubscribeEvent(priority = EventPriority.LOWEST) fun onHurtEvent(event: LivingHurtEvent) { if (event.isCanceled) { return @@ -809,8 +808,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn const val CAPABILITY_KEY = "otm_player" val CAPABILITY_LOCATION = ResourceLocation(OverdriveThatMatters.MOD_ID, CAPABILITY_KEY) - @SubscribeEvent - fun onAttachCapabilityEvent(event: AttachCapabilitiesEvent) { + fun onAttachCapabilityEvent(event: AttachCapabilitiesEvent) { val ent = event.`object` if (ent is Player) { @@ -818,18 +816,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn } } - @SubscribeEvent fun onPlayerChangeDimensionEvent(event: PlayerEvent.PlayerChangedDimensionEvent) { event.entity.getCapability(MatteryCapability.MATTERY_PLAYER) .ifPresentK { it.invalidateNetworkState() } } - @SubscribeEvent(priority = EventPriority.LOWEST) fun onPlayerDeath(event: LivingDeathEvent) { - if (event.isCanceled) { - return - } - val ply = event.entity as? Player ?: return val mattery = ply.matteryPlayer ?: return @@ -856,7 +848,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn } } - @SubscribeEvent fun onPlayerCloneEvent(event: PlayerEvent.Clone) { val it = event.entity.matteryPlayer ?: return @@ -889,7 +880,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn private val itemPickupTicks = WeakHashMap>() - @SubscribeEvent(priority = EventPriority.LOW) fun onPickupEvent(event: EntityItemPickupEvent) { if (event.item.owner != null && event.item.owner != event.entity.uuid && event.item.age < 200 || event.item.item.isEmpty) { return diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/AbstractMatteryDrive.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/AbstractMatteryDrive.kt index a9039d0c9..1fbda2ec0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/AbstractMatteryDrive.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/AbstractMatteryDrive.kt @@ -1,21 +1,14 @@ package ru.dbotthepony.mc.otm.capability.drive -import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap -import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap import it.unimi.dsi.fastutil.objects.ObjectArraySet import kotlin.jvm.JvmOverloads import java.util.UUID import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.ListTag -import net.minecraft.nbt.LongTag import net.minecraft.nbt.Tag import org.apache.logging.log4j.LogManager -import ru.dbotthepony.mc.otm.core.BigInteger -import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.core.isPositive -import ru.dbotthepony.mc.otm.core.serializeNBT -import ru.dbotthepony.mc.otm.ifHas -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.storage.* import java.math.BigInteger import java.util.ArrayList diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/DrivePool.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/DrivePool.kt index 8f2912ad9..33180d029 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/DrivePool.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/DrivePool.kt @@ -36,7 +36,6 @@ import java.util.ArrayList * 5. Mods which check items for being stack-able even with stack size of 1 gonna compare nbt tag, * which will be performance tanking due to clause 1. */ -@Suppress("unused") object DrivePool { private val LOGGER = LogManager.getLogger() private val pool = Object2ObjectAVLTreeMap() @@ -130,7 +129,6 @@ object DrivePool { } } - @SubscribeEvent(priority = EventPriority.LOWEST) fun onServerPostTick(event: ServerTickEvent) { if (event.phase == TickEvent.Phase.END) { if (exception != null) { @@ -152,7 +150,6 @@ object DrivePool { return Thread.currentThread() === serverThread } - @SubscribeEvent(priority = EventPriority.HIGHEST) fun serverStartEvent(event: ServerAboutToStartEvent) { if (thread?.isAlive == true) { LOGGER.error("FMLServerStartedEvent fired twice.") @@ -172,7 +169,6 @@ object DrivePool { thread = Thread(null, this::thread, "Overdrive That Matters DrivePool IO").also { it.start() } } - @SubscribeEvent(priority = EventPriority.HIGHEST) fun serverStopEvent(event: ServerStoppingEvent) { val thread = thread @@ -189,7 +185,6 @@ object DrivePool { pool.clear() } - @SubscribeEvent fun onWorldSave(event: LevelEvent.Save) { writeBacklog() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/ItemMatteryDrive.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/ItemMatteryDrive.kt index 74a66ad21..6cd728abb 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/ItemMatteryDrive.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/drive/ItemMatteryDrive.kt @@ -6,12 +6,11 @@ import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Items import net.minecraftforge.registries.ForgeRegistries -import net.minecraftforge.registries.RegistryManager import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.core.BigInteger -import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.serializeNBT -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.storage.IStorageTuple import ru.dbotthepony.mc.otm.storage.ItemStackWrapper import ru.dbotthepony.mc.otm.storage.StorageStackType diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/API.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/API.kt index 4362f0e79..c7ebe7311 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/API.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/API.kt @@ -5,6 +5,7 @@ import ru.dbotthepony.mc.otm.core.ImpreciseFraction import java.util.* import java.util.function.Predicate import java.util.stream.Collectors +import java.util.stream.Stream interface IMatterHandler { val storedMatter: ImpreciseFraction @@ -14,6 +15,7 @@ interface IMatterHandler { fun receiveMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction fun extractMatterOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction fun extractMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction + val direction: MatterDirection val missingMatter: ImpreciseFraction get() = maxStoredMatter.minus(storedMatter).moreThanZero() @@ -27,42 +29,44 @@ interface IMatterHandler { enum class MatterDirection { RECEIVE, EXTRACT, BIDIRECTIONAL } -interface IMatterTaskProvider { +interface IReplicationTaskProvider { /** - * @return immutable collection of tasks that can be allocated by a worker + * It must return new stream each time */ - val tasks: Collection + val replicationTasks: Stream> /** - * @return immutable collection of all stored tasks, even fully allocated by workers + * It must return new stream each time */ - val allTasks: Collection + val allReplicationTasks: Stream> /** * Allocates (marks as work-in-progress) a task - * by incrementing it's in_progress by 1 - * and shrinking required by 1 + * by incrementing it's [IReplicationTask.inProgress] by 1 + * and shrinking [IReplicationTask.required] by 1 * - * If required == 0, it should not be returned by this method + * If [IReplicationTask.required] == 0, it should not be returned by this method * @param simulate whenever to change internal state * @return MatterTaskAllocation(task, pattern) that should be performed, or null if no work is available */ - fun allocateTask(simulate: Boolean): MatterTaskAllocation? + fun allocateTask(simulate: Boolean): ReplicationTaskAllocation? /** * Notify about task completion. If this provider indeed contain this task, it should * shrink in_progress by 1 * If in_progress == 0 and required == 0, it should discard the task - * @param task task being completed. this method should ignore tasks that are not owned by it. + * @param taskId task being completed. this method should ignore tasks that are not owned by it. * @return whenever task indeed belong to this provider and internal state was updated */ - fun notifyTaskCompletion(task: MatterTask): Boolean + fun notifyTaskCompletion(taskId: UUID): Boolean /** * @param id uuid of task * @return MatterTask that this capability holds with this id, or null */ - fun getTask(id: UUID): MatterTask? + fun getTask(id: UUID): IReplicationTask<*>? { + return allReplicationTasks.filter { it.id == id }.findAny().orElse(null) + } /** * Destroys all tasks this capability contains @@ -72,50 +76,36 @@ interface IMatterTaskProvider { interface IPatternStorage { /** - * @return unmodifiable collection of stored patterns + * It must return new stream each time */ - val storedPatterns: Collection + val storedPatterns: Stream - fun findPatterns(item: Item): Collection { - return findPatterns { item2: PatternState -> item == item2.item() } + fun findPatterns(item: Item): Collection { + return findPatterns { item == it.item } } - fun findPatterns(predicate: Predicate?): Collection { - return storedPatterns.stream().filter(predicate).collect(Collectors.toList()) + fun findPatterns(predicate: Predicate): Collection { + return storedPatterns.filter(predicate).collect(Collectors.toList()) } - fun findPattern(item: Item): PatternState? { - return findPattern { item2: PatternState -> item == item2.item() } + fun findPattern(item: Item): IPatternState? { + return storedPatterns.filter { it.item == item }.findAny().orElse(null) } - fun findPattern(predicate: Predicate): PatternState? { - for (pattern in storedPatterns) { - if (predicate.test(pattern)) { - return pattern - } - } - - return null + fun getPattern(id: UUID?): IPatternState? { + return storedPatterns.filter { it.id == id }.findAny().orElse(null) } - fun getPattern(id: UUID?): PatternState? { - id ?: return null - - for (pattern in storedPatterns) { - if (pattern.id == id) { - return pattern - } - } - - return null + fun hasPattern(item: Item): Boolean { + return storedPatterns.filter { it.item == item }.findAny().isPresent } - fun hasPattern(state: PatternState): Boolean { - return getPattern(state.id) != null + fun hasPattern(state: IPatternState): Boolean { + return hasPattern(state.id) } fun hasPattern(id: UUID?): Boolean { - return getPattern(id) != null + return storedPatterns.filter { it.id == id }.findAny().isPresent } val capacity: Int @@ -126,17 +116,17 @@ interface IPatternStorage { * and if it fail, try only_update = false * * @param pattern pattern to be inserted or update value from - * @param only_update do not insert new pattern if this pattern's UUID is not matched + * @param onlyUpdate do not insert new pattern if this pattern's UUID is not matched * @param simulate whenever to affect state * @return record of status of the operation (at status() FAIL, UPDATED, INSERTED) as well as new_state and old_state */ - fun insertPattern(pattern: PatternState, only_update: Boolean, simulate: Boolean): PatternInsertStatus + fun insertPattern(pattern: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus - fun insertPattern(pattern: PatternState, simulate: Boolean): PatternInsertStatus { + fun insertPattern(pattern: IPatternState, simulate: Boolean): PatternInsertStatus { return insertPattern(pattern, false, simulate) } - fun updatePattern(pattern: PatternState, simulate: Boolean): PatternInsertStatus { + fun updatePattern(pattern: IPatternState, simulate: Boolean): PatternInsertStatus { return insertPattern(pattern, true, simulate) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/Data.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/Data.kt index 9ca6150db..78df561cc 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/Data.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/Data.kt @@ -8,17 +8,17 @@ private enum class PatternInsertResult { sealed class PatternInsertStatus( private val status: PatternInsertResult, - val newState: PatternState?, - val oldState: PatternState? + val newState: IPatternState?, + val oldState: IPatternState? ) { - val isFailed get() = status === PatternInsertResult.FAIL - val isUpdated get() = status === PatternInsertResult.UPDATED - val isInserted get() = status === PatternInsertResult.INSERTED + val isFailed get() = status == PatternInsertResult.FAIL + val isUpdated get() = status == PatternInsertResult.UPDATED + val isInserted get() = status == PatternInsertResult.INSERTED } object PatternInsertFailure : PatternInsertStatus(PatternInsertResult.FAIL, null, null) -class PatternInsertUpdated(new: PatternState, old: PatternState) : PatternInsertStatus(PatternInsertResult.UPDATED, new, old) -class PatternInsertInserted(new: PatternState) : PatternInsertStatus(PatternInsertResult.INSERTED, new, null) +class PatternInsertUpdated(new: IPatternState, old: IPatternState) : PatternInsertStatus(PatternInsertResult.UPDATED, new, old) +class PatternInsertInserted(new: IPatternState) : PatternInsertStatus(PatternInsertResult.INSERTED, new, null) @JvmRecord -data class MatterTaskAllocation(val task: MatterTask, val pattern: PatternState?) +data class ReplicationTaskAllocation(val task: IReplicationTask<*>, val pattern: IPatternState?) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterHandlerImpl.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterHandlerImpl.kt index 45a24fc9a..4adc14a74 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterHandlerImpl.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/MatterHandlerImpl.kt @@ -4,7 +4,8 @@ import net.minecraft.nbt.CompoundTag import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.LazyOptional import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.core.set open class MatterHandlerImpl @JvmOverloads constructor( protected val listener: Runnable?, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/PatternState.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/PatternState.kt new file mode 100644 index 000000000..c53bcc134 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/PatternState.kt @@ -0,0 +1,146 @@ +package ru.dbotthepony.mc.otm.capability.matter + +import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.Tag +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.item.Item +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.Items +import net.minecraftforge.registries.ForgeRegistries +import ru.dbotthepony.mc.otm.core.* +import java.util.* + +sealed interface IPatternState { + val id: UUID + val item: Item + val researchPercent: Double + + fun asMutable(): MutablePatternState + fun asImmutable() : PatternState + + fun matchId(other: IPatternState): Boolean { + return other.id == id + } + + fun copyAsMutable( + id: UUID = this.id, + item: Item = this.item, + researchPercent: Double = this.researchPercent, + ): MutablePatternState { + return MutablePatternState(id, item, researchPercent) + } + + fun copyAsImmutable( + id: UUID = this.id, + item: Item = this.item, + researchPercent: Double = this.researchPercent, + ) : PatternState { + return PatternState(id, item, researchPercent) + } + + fun stack(count: Int = 1): ItemStack { + return ItemStack(item, count) + } + + fun serializeNBT(): CompoundTag { + return CompoundTag().also { + it["id"] = id + it["item"] = item.registryName!!.toString() + it["researchPercent"] = researchPercent + } + } + + fun write(buff: FriendlyByteBuf) { + buff.writeUUID(id) + buff.writeItemType(item) + buff.writeDouble(researchPercent) + } +} + +private fun deserializeNBT(nbt: Tag?, mutable: Boolean): IPatternState? { + if (nbt !is CompoundTag) + return null + + if (!nbt.contains("id", "researchPercent", "item")) + return null + + val id = nbt.getUUID("id") + val researchPercent = nbt.getDouble("researchPercent") + val item = ForgeRegistries.ITEMS.getValue(ResourceLocation(nbt.getString("item"))) ?: return null + + if (item == Items.AIR) + return null + + if (mutable) { + return MutablePatternState(id, item, researchPercent) + } else { + return PatternState(id, item, researchPercent) + } +} + +private fun read(buff: FriendlyByteBuf, mutable: Boolean): IPatternState? { + val id = buff.readUUID() + val item = buff.readItemType() + val researchPercent = buff.readDouble() + + item ?: return null + + if (mutable) { + return MutablePatternState(id, item, researchPercent) + } else { + return PatternState(id, item, researchPercent) + } +} + +data class PatternState( + override val id: UUID, + override val item: Item, + override val researchPercent: Double, +) : IPatternState { + override fun asMutable(): MutablePatternState { + return MutablePatternState(id, item, researchPercent) + } + + override fun asImmutable(): PatternState { + return this + } + + companion object { + fun deserializeNBT(tag: Tag?): PatternState? { + return deserializeNBT(tag, false) as PatternState? + } + + fun read(buff: FriendlyByteBuf): PatternState? { + return read(buff, false) as PatternState? + } + } +} + +data class MutablePatternState( + override val id: UUID, + override val item: Item, + override var researchPercent: Double, +) : IPatternState { + override fun asMutable(): MutablePatternState { + return this + } + + override fun asImmutable(): PatternState { + return PatternState(id, item, researchPercent) + } + + companion object { + fun deserializeNBT(tag: Tag?): MutablePatternState? { + return deserializeNBT(tag, true) as MutablePatternState? + } + + fun read(buff: FriendlyByteBuf): MutablePatternState? { + return read(buff, true) as MutablePatternState? + } + } +} + +fun FriendlyByteBuf.writePatternState(state: IPatternState) = state.write(this) +fun FriendlyByteBuf.readPatternState() = PatternState.read(this) +fun FriendlyByteBuf.readMutablePatternState() = MutablePatternState.read(this) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/ReplicationTask.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/ReplicationTask.kt new file mode 100644 index 000000000..0dd3991d9 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/matter/ReplicationTask.kt @@ -0,0 +1,210 @@ +package ru.dbotthepony.mc.otm.capability.matter + +import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.Tag +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.item.Item +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.Items +import net.minecraftforge.registries.ForgeRegistries +import ru.dbotthepony.mc.otm.core.readItemType +import ru.dbotthepony.mc.otm.core.registryName +import ru.dbotthepony.mc.otm.core.set +import ru.dbotthepony.mc.otm.core.writeItemType +import java.util.UUID + +sealed interface IReplicationTask> { + val id: UUID + val patternId: UUID? + val item: Item + val inProgress: Int + val finished: Int + val required: Int + + fun asMutable(): MutableReplicationTask + fun asImmutable(): ReplicationTask + + val total get() = inProgress + finished + required + + fun copyAsMutable( + id: UUID = this.id, + patternId: UUID? = this.patternId, + item: Item = this.item, + inProgress: Int = this.inProgress, + finished: Int = this.finished, + required: Int = this.required, + ): MutableReplicationTask { + return MutableReplicationTask(id, patternId, item, inProgress, finished, required) + } + + fun copyAsImmutable( + id: UUID = this.id, + patternId: UUID? = this.patternId, + item: Item = this.item, + inProgress: Int = this.inProgress, + finished: Int = this.finished, + required: Int = this.required, + ): ReplicationTask { + return ReplicationTask(id, patternId, item, inProgress, finished, required) + } + + fun matchId(other: IReplicationTask<*>): Boolean { + return other.id == id + } + + fun stack(count: Int = 1): ItemStack { + return ItemStack(item, count) + } + + fun allocate(amount: Int = 1): S + fun finish(amount: Int = 1): S + + fun serializeNBT(): CompoundTag { + return CompoundTag().also { + it["id"] = id + + if (patternId != null) + it["patternId"] = patternId!! + + it["item"] = item.registryName!!.toString() + it["inProgress"] = inProgress + it["finished"] = finished + it["required"] = required + } + } + + fun write(buff: FriendlyByteBuf) { + buff.writeUUID(id) + + buff.writeBoolean(patternId != null) + patternId?.let(buff::writeUUID) + + buff.writeItemType(item) + + buff.writeInt(inProgress) + buff.writeInt(finished) + buff.writeInt(required) + } +} + +private fun deserializeNBT(nbt: Tag?, mutable: Boolean): IReplicationTask<*>? { + if (nbt !is CompoundTag) + return null + + if (!nbt.contains("id") || !nbt.contains("inProgress") || !nbt.contains("finished") || !nbt.contains("required") || !nbt.contains("item")) + return null + + val item = ForgeRegistries.ITEMS.getValue(ResourceLocation(nbt.getString("item"))) ?: return null + + if (item == Items.AIR) + return null + + val id = nbt.getUUID("id") + val patternId = if (nbt.contains("patternId")) nbt.getUUID("patternId") else null + + val inProgress = nbt.getInt("inProgress") + val finished = nbt.getInt("finished") + val required = nbt.getInt("required") + + if (mutable) { + return MutableReplicationTask(id, patternId, item, inProgress, finished, required) + } else { + return ReplicationTask(id, patternId, item, inProgress, finished, required) + } +} + +private fun read(buff: FriendlyByteBuf, mutable: Boolean): IReplicationTask<*>? { + val id = buff.readUUID() + val patternId: UUID? = if (buff.readBoolean()) buff.readUUID() else null + val item = buff.readItemType() + val inProgress = buff.readInt() + val finished = buff.readInt() + val required = buff.readInt() + + item ?: return null + + if (mutable) { + return MutableReplicationTask(id, patternId, item, inProgress, finished, required) + } else { + return ReplicationTask(id, patternId, item, inProgress, finished, required) + } +} + +data class ReplicationTask( + override val id: UUID, + override val patternId: UUID?, + override val item: Item, + override val inProgress: Int, + override val finished: Int, + override val required: Int +) : IReplicationTask { + override fun asMutable(): MutableReplicationTask { + return MutableReplicationTask(id, patternId, item, inProgress, finished, required) + } + + override fun asImmutable(): ReplicationTask { + return this + } + + override fun allocate(amount: Int): ReplicationTask { + return ReplicationTask(id, patternId, item, inProgress + amount, finished, required - amount) + } + + override fun finish(amount: Int): ReplicationTask { + return ReplicationTask(id, patternId, item, inProgress - amount, finished + amount, required) + } + + companion object { + fun deserializeNBT(nbt: Tag?): ReplicationTask? { + return deserializeNBT(nbt, false) as ReplicationTask? + } + + fun read(buff: FriendlyByteBuf): ReplicationTask? { + return read(buff, false) as ReplicationTask? + } + } +} + +data class MutableReplicationTask( + override val id: UUID, + override val patternId: UUID?, + override val item: Item, + override var inProgress: Int, + override var finished: Int, + override var required: Int +) : IReplicationTask { + override fun asMutable(): MutableReplicationTask { + return this + } + + override fun asImmutable(): ReplicationTask { + return ReplicationTask(id, patternId, item, inProgress, finished, required) + } + + override fun allocate(amount: Int): MutableReplicationTask { + inProgress += amount + finished -= amount + return this + } + + override fun finish(amount: Int): MutableReplicationTask { + finished += amount + inProgress -= amount + return this + } + + companion object { + fun deserializeNBT(nbt: Tag?): MutableReplicationTask? { + return deserializeNBT(nbt, true) as MutableReplicationTask? + } + + fun read(buff: FriendlyByteBuf): MutableReplicationTask? { + return read(buff, true) as MutableReplicationTask? + } + } +} + +fun FriendlyByteBuf.writeReplicationTask(task: IReplicationTask<*>) = task.write(this) +fun FriendlyByteBuf.readReplicationTask() = ReplicationTask.read(this) +fun FriendlyByteBuf.readMutableReplicationTask() = MutableReplicationTask.read(this) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientEventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientEventHandler.kt new file mode 100644 index 000000000..1f6a6943f --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/ClientEventHandler.kt @@ -0,0 +1,53 @@ +package ru.dbotthepony.mc.otm.client + +import net.minecraft.client.gui.screens.inventory.InventoryScreen +import net.minecraftforge.client.event.MovementInputUpdateEvent +import net.minecraftforge.client.event.ScreenEvent +import ru.dbotthepony.mc.otm.capability.matteryPlayer +import ru.dbotthepony.mc.otm.client.screen.ExoSuitInventoryScreen +import ru.dbotthepony.mc.otm.registry.AndroidFeatures + +object ClientEventHandler { + fun inputEvent(event: MovementInputUpdateEvent) { + val ply = event.entity + val input = event.input + + val cap = ply.matteryPlayer ?: return + + if (cap.hasFeature(AndroidFeatures.AIR_BAGS)) + return + + if (ply.abilities.mayfly) { + cap.lastJumpTicks = 14 + } else { + if (ply.isInWater) { + if (ply.isOnGround) { + cap.lastJumpTicks = 14 + } + + if (ply.isSwimming) { + ply.isSwimming = false + } + + if (cap.lastJumpTicks <= 0) { + input.jumping = false + input.up = false + } else { + cap.lastJumpTicks-- + } + } + } + } + + fun screenOpen(event: ScreenEvent.Opening) { + if (minecraft.player?.isCreative == true) { + return + } + + val player = minecraft.player?.matteryPlayer ?: return + + if (player.hasExoSuit && event.newScreen is InventoryScreen) { + event.newScreen = ExoSuitInventoryScreen(player.exoSuitMenu) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/EventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/EventHandler.kt deleted file mode 100644 index 8f52e8aa7..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/EventHandler.kt +++ /dev/null @@ -1,56 +0,0 @@ -package ru.dbotthepony.mc.otm.client - -import net.minecraft.client.gui.screens.inventory.InventoryScreen -import net.minecraftforge.client.event.MovementInputUpdateEvent -import net.minecraftforge.client.event.ScreenEvent -import net.minecraftforge.eventbus.api.SubscribeEvent -import ru.dbotthepony.mc.otm.capability.matteryPlayer -import ru.dbotthepony.mc.otm.client.screen.ExoSuitInventoryScreen -import ru.dbotthepony.mc.otm.registry.AndroidFeatures - -@SubscribeEvent -@Suppress("unused") -fun inputEvent(event: MovementInputUpdateEvent) { - val ply = event.entity - val input = event.input - - val cap = ply.matteryPlayer ?: return - - if (cap.hasFeature(AndroidFeatures.AIR_BAGS)) - return - - if (ply.abilities.mayfly) { - cap.lastJumpTicks = 14 - } else { - if (ply.isInWater) { - if (ply.isOnGround) { - cap.lastJumpTicks = 14 - } - - if (ply.isSwimming) { - ply.isSwimming = false - } - - if (cap.lastJumpTicks <= 0) { - input.jumping = false - input.up = false - } else { - cap.lastJumpTicks-- - } - } - } -} - -@SubscribeEvent -@Suppress("unused") -fun screenOpen(event: ScreenEvent.Opening) { - if (minecraft.player?.isCreative == true) { - return - } - - val player = minecraft.player?.matteryPlayer ?: return - - if (player.hasExoSuit && event.newScreen is InventoryScreen) { - event.newScreen = ExoSuitInventoryScreen(player.exoSuitMenu) - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/Ext.kt index b438fb865..4103e8d04 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/Ext.kt @@ -2,6 +2,12 @@ package ru.dbotthepony.mc.otm.client import net.minecraft.client.Minecraft import net.minecraft.client.gui.Font +import net.minecraft.client.resources.sounds.SimpleSoundInstance +import net.minecraft.sounds.SoundEvents inline val minecraft: Minecraft get() = Minecraft.getInstance() inline val font: Font get() = minecraft.font + +fun playGuiClickSound() { + minecraft.soundManager.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0f)) +} 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 c5d02ded5..00c3dad64 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt @@ -18,14 +18,13 @@ import net.minecraftforge.client.gui.overlay.GuiOverlayManager import net.minecraftforge.eventbus.api.EventPriority import net.minecraftforge.eventbus.api.SubscribeEvent import ru.dbotthepony.mc.otm.OverdriveThatMatters -import ru.dbotthepony.mc.otm.TextComponent -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.core.RGBAColor -import ru.dbotthepony.mc.otm.ifPresentK +import ru.dbotthepony.mc.otm.core.ifPresentK import java.util.* object MatteryGUI { @@ -40,8 +39,6 @@ object MatteryGUI { private val button_shaker = Random() - @SubscribeEvent - @Suppress("unused") fun onScreenRender(event: ScreenEvent.Render.Pre) { if (knownButtonScreen != null && knownButton == null) { for (widget in knownButtonScreen!!.renderables) { @@ -88,8 +85,6 @@ object MatteryGUI { } } - @SubscribeEvent(priority = EventPriority.LOWEST) - @Suppress("unused") fun onOpenGUIEvent(event: ScreenEvent.Opening) { knownButtonX = -1 knownButtonY = -1 @@ -199,14 +194,10 @@ object MatteryGUI { popScissorRect() } - @SubscribeEvent - @Suppress("unused") fun onRenderGuiEvent(event: RenderGuiEvent.Post) { showIteration(event) } - @SubscribeEvent(priority = EventPriority.HIGH) - @Suppress("unused") fun onLayerRenderEvent(event: RenderGuiOverlayEvent.Pre) { if (event.overlay != FOOD_LEVEL_ELEMENT && event.overlay != AIR_LEVEL_ELEMENT) { return 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 1c4715b39..d0e455e9c 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 @@ -11,7 +11,7 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider import net.minecraft.world.phys.Vec3 import org.lwjgl.opengl.GL30 -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity import ru.dbotthepony.mc.otm.capability.matteryPlayer 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 2d299b81c..e6cf2ac62 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 @@ -6,7 +6,7 @@ import net.minecraft.client.renderer.MultiBufferSource import net.minecraft.client.renderer.blockentity.BlockEntityRenderer import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider import net.minecraft.core.Direction -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.EnergyCounterBlock import ru.dbotthepony.mc.otm.block.entity.EnergyCounterBlockEntity import ru.dbotthepony.mc.otm.client.render.* 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 ab12d926a..79dd06175 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 @@ -10,12 +10,12 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider import net.minecraft.client.renderer.texture.OverlayTexture import net.minecraft.core.Direction -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.BlackHoleBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.core.* import kotlin.math.PI diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt index 4760d6eb1..b4712fdea 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt @@ -7,16 +7,14 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap import it.unimi.dsi.fastutil.ints.Int2ObjectFunction import net.minecraft.ChatFormatting import net.minecraft.client.Minecraft -import net.minecraft.client.resources.sounds.SimpleSoundInstance import net.minecraft.network.chat.Component -import net.minecraft.sounds.SoundEvents import net.minecraft.world.entity.player.Inventory -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.android.AndroidResearch import ru.dbotthepony.mc.otm.android.AndroidResearchType import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability -import ru.dbotthepony.mc.otm.client.minecraft +import ru.dbotthepony.mc.otm.client.playGuiClickSound import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.render.drawColor import ru.dbotthepony.mc.otm.client.render.drawLine @@ -24,7 +22,7 @@ import ru.dbotthepony.mc.otm.client.render.drawRect import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.core.RGBAColor -import ru.dbotthepony.mc.otm.ifPresentK +import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.menu.AndroidStationMenu import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel import ru.dbotthepony.mc.otm.network.AndroidResearchRequestPacket @@ -383,7 +381,7 @@ private class AndroidResearchButton( MatteryPlayerNetworkChannel.sendToServer(AndroidResearchRequestPacket(node.type)) } - minecraft.soundManager.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0f)) + playGuiClickSound() } return true @@ -479,6 +477,7 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { if (isPreview) { + playGuiClickSound() openResearchTree() return true } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ChemicalGeneratorScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ChemicalGeneratorScreen.kt index 0f6a6ffe3..af265b0ec 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ChemicalGeneratorScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ChemicalGeneratorScreen.kt @@ -2,9 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.screen.panels.* -import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.menu.ChemicalGeneratorMenu diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt index 6700bd60a..2ef781e9c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt @@ -4,9 +4,10 @@ import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory import net.minecraft.world.item.ItemStack -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel +import ru.dbotthepony.mc.otm.core.maxScrollDivision import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem import ru.dbotthepony.mc.otm.menu.DriveViewerMenu @@ -51,15 +52,15 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp val grid = GridPanel(this, frame, 28f, 16f, GRID_WIDTH * 18f, GRID_HEIGHT * 18f, GRID_WIDTH, GRID_HEIGHT) - val scrollBar = ContinuousScrollBarPanel(this, frame, 192f, 14f, 92f) - scrollBar.setupRowMultiplier { menu.networkedItemView.itemCount / GRID_WIDTH } + val scrollBar = DiscreteScrollBarPanel(this, frame, { maxScrollDivision(menu.networkedItemView.itemCount, GRID_WIDTH) }, { _, _, _ -> }, 192f, 14f, 92f) + views.add(grid) views.add(scrollBar) for (i in 0 until GRID_WIDTH * GRID_HEIGHT) { object : AbstractSlotPanel(this@DriveViewerScreen, grid, 0f, 0f) { override fun getItemStack(): ItemStack { - val index = i + scrollBar.getScroll(menu.networkedItemView.sortedView.size / GRID_WIDTH) + val index = i + scrollBar.scroll * GRID_WIDTH return menu.networkedItemView.sortedView.getOrNull(index)?.stack?.item ?: ItemStack.EMPTY } @@ -68,7 +69,7 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp } override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { - val index = i + scrollBar.getScroll(GRID_WIDTH) + val index = i + scrollBar.scroll * GRID_WIDTH menu.networkedItemView.mouseClick(index, button) return true } @@ -81,7 +82,7 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp override fun getItemStackTooltip(stack: ItemStack): List { return super.getItemStackTooltip(stack).also { it as MutableList - val index = i + scrollBar.getScroll(menu.networkedItemView.sortedView.size / GRID_WIDTH) + val index = i + scrollBar.scroll * GRID_WIDTH val realStack = menu.networkedItemView.sortedView.getOrNull(index)!!.stack it.add(TranslatableComponent("otm.gui.item_amount", realStack.count.toString())) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/EnergyCounterScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/EnergyCounterScreen.kt index 9caf1f4b5..54c8dc5d3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/EnergyCounterScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/EnergyCounterScreen.kt @@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.client.screen import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.core.formatPower import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ExoSuitInventoryScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ExoSuitInventoryScreen.kt index cac0ee43c..1b027f2fc 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ExoSuitInventoryScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ExoSuitInventoryScreen.kt @@ -3,9 +3,8 @@ package ru.dbotthepony.mc.otm.client.screen import com.mojang.blaze3d.vertex.PoseStack import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap import it.unimi.dsi.fastutil.ints.Int2ObjectFunction -import net.minecraft.client.gui.screens.inventory.InventoryScreen import net.minecraft.world.inventory.Slot -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.render.element import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.menu.ExoSuitInventoryMenu @@ -13,36 +12,6 @@ import ru.dbotthepony.mc.otm.network.ExoSuitMenuOpen import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel class ExoSuitInventoryScreen(menu: ExoSuitInventoryMenu) : MatteryScreen(menu, TranslatableComponent("otm.gui.exosuit")) { - private val slotRows = Int2ObjectAVLTreeMap() - - private fun getSlotsRow(index: Int): EditablePanel { - return slotRows.computeIfAbsent(index, Int2ObjectFunction { - val canvas = object : EditablePanel(this@ExoSuitInventoryScreen, null, width = AbstractSlotPanel.SIZE * 9f, height = AbstractSlotPanel.SIZE) { - override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean { - return false - } - } - - val offset = it * 9 - - if (menu.combinedInventorySlots.size <= offset) { - return@Int2ObjectFunction canvas - } - - for (i in 0 .. (8).coerceAtMost(menu.combinedInventorySlots.size - offset - 1)) { - val slot = object : SlotPanel(this@ExoSuitInventoryScreen, canvas, menu.combinedInventorySlots[offset + i]) { - override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean { - return false - } - } - - slot.dock = Dock.LEFT - } - - return@Int2ObjectFunction canvas - }) - } - override fun makeMainFrame(): FramePanel { val frame = FramePanel(this, width = 200f, height = 180f, title = this.title) @@ -53,16 +22,16 @@ class ExoSuitInventoryScreen(menu: ExoSuitInventoryMenu) : MatteryScreen for (i in old .. old + 2) { - getSlotsRow(i).visible = false + getInventorySlotsRow(i).visible = false } for (i in new .. new + 2) { - val row = getSlotsRow(i) + val row = getInventorySlotsRow(i) row.visible = true row.y = (i - new) * AbstractSlotPanel.SIZE row.parent = mainInventoryLine @@ -83,7 +52,7 @@ class ExoSuitInventoryScreen(menu: ExoSuitInventoryMenu) : MatteryScreen(menu, inventory, title) { override fun makeMainFrame(): FramePanel { - val frame = FramePanel(this@ItemMonitorScreen, null, 0f, 0f, FRAME_WIDTH, FRAME_HEIGHT, getTitle()) + val frame = FramePanel(this@ItemMonitorScreen, null, 0f, 0f, 1f, 1f, getTitle()) val topPanel = EditablePanel(this, frame) topPanel.height = ITEM_GRID_HEIGHT * 18f @@ -35,11 +36,13 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp bottomPanel.dock = Dock.TOP bottomPanel.setDockMargin(top = 6f) - frame.height = topPanel.height + bottomPanel.height + frame.dockPadding.top + frame.dockPadding.bottom + 6f + frame.height = topPanel.height + bottomPanel.height + frame.dockPadding.top + frame.dockPadding.bottom + 26f frame.width = 178f + frame.dockPadding.left + frame.dockPadding.right - val viewScrollBar = ContinuousScrollBarPanel(this, topPanel, 28f + ITEM_GRID_WIDTH * 18f + 2f, 16f, ITEM_GRID_HEIGHT * 18f) - viewScrollBar.setupRowMultiplier { equalDownDivision(menu.networkedItemView.itemCount, ITEM_GRID_WIDTH) } + val viewScrollBar = DiscreteScrollBarPanel(this, topPanel, + { maxScrollDivision(menu.networkedItemView.itemCount, ITEM_GRID_WIDTH) }, + { _, _, _ -> }, + 28f + ITEM_GRID_WIDTH * 18f + 2f, 16f, ITEM_GRID_HEIGHT * 18f) viewScrollBar.dock = Dock.RIGHT viewScrollBar.setDockMargin(left = 2f) @@ -49,7 +52,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp for (i in 0 until ITEM_GRID_WIDTH * ITEM_GRID_HEIGHT) { object : AbstractSlotPanel(this@ItemMonitorScreen, gridPanel) { - private val index get() = i + viewScrollBar.getScroll(equalDownDivision(menu.networkedItemView.itemCount, ITEM_GRID_WIDTH)) * ITEM_GRID_WIDTH + private val index get() = i + viewScrollBar.scroll * ITEM_GRID_WIDTH override fun getItemStack(): ItemStack { return menu.networkedItemView.sortedView.getOrNull(index)?.stack?.item ?: ItemStack.EMPTY @@ -116,7 +119,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp arrowAndButtons.dock = Dock.LEFT arrowAndButtons.setDockMargin(left = 4f) - val arrowLineTop = EditablePanel(this, arrowAndButtons, y = 0f, height = 8f, width = arrowAndButtons.width) + EditablePanel(this, arrowAndButtons, y = 0f, height = 8f, width = arrowAndButtons.width) val arrowLine = EditablePanel(this, arrowAndButtons, y = 38f, height = 8f, width = arrowAndButtons.width) @@ -168,7 +171,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp craftingHistory.dock = Dock.LEFT craftingHistory.setDockMargin(left = 4f) - val craftingHistoryScroll = ContinuousScrollBarPanel(this, bottomPanel, 0f, 0f, 0f) + val craftingHistoryScroll = DiscreteScrollBarPanel(this, bottomPanel, { 0 }, { _, _, _ -> }) craftingHistoryScroll.dock = Dock.LEFT craftingHistoryScroll.setDockMargin(left = 2f) @@ -184,13 +187,23 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp } } + val bottomStrip = EditablePanel(this, frame, height = AbstractSlotPanel.SIZE) + bottomStrip.dock = Dock.BOTTOM + + BatterySlotPanel(this, bottomStrip, menu.batterySlot).also { + it.dock = Dock.LEFT + it.dockRight = 3f + } + + TallHorizontalPowerGaugePanel(this, bottomStrip, menu.powerWidget).also { + it.dock = Dock.FILL + it.dockResize = DockResizeMode.NONE + } + return frame } companion object { - const val FRAME_WIDTH = 240f - const val FRAME_HEIGHT = 210f - const val ITEM_GRID_WIDTH = 9 const val ITEM_GRID_HEIGHT = 5 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterBottlerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterBottlerScreen.kt index 869172e13..4e42721fa 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterBottlerScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterBottlerScreen.kt @@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.client.screen import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterPanelScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterPanelScreen.kt new file mode 100644 index 000000000..bacdf2cac --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterPanelScreen.kt @@ -0,0 +1,295 @@ +package ru.dbotthepony.mc.otm.client.screen + +import net.minecraft.ChatFormatting +import net.minecraft.client.gui.components.EditBox +import net.minecraft.network.chat.Component +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.item.ItemStack +import ru.dbotthepony.mc.otm.capability.matter.IPatternState +import ru.dbotthepony.mc.otm.capability.matter.IReplicationTask +import ru.dbotthepony.mc.otm.capability.matter.PatternState +import ru.dbotthepony.mc.otm.client.screen.panels.* +import ru.dbotthepony.mc.otm.core.TranslatableComponent +import ru.dbotthepony.mc.otm.core.maxScrollDivision +import ru.dbotthepony.mc.otm.menu.MatterPanelMenu +import ru.dbotthepony.mc.otm.menu.ReplicationRequestPacket +import ru.dbotthepony.mc.otm.network.MenuNetworkChannel + +class MatterPanelScreen( + menu: MatterPanelMenu, + inventory: Inventory, + title: Component +) : MatteryScreen(menu, inventory, title) { + override fun makeMainFrame(): FramePanel { + var isPatternView = true + + val frame = FramePanel.padded(this, null, GRID_WIDTH * AbstractSlotPanel.SIZE + ScrollBarConstants.WIDTH + 4f, GRID_HEIGHT * AbstractSlotPanel.SIZE, title) + + val scrollBar = DiscreteScrollBarPanel(this, frame, { + if (isPatternView) { + maxScrollDivision(menu.patterns.size, GRID_WIDTH) + } else { + maxScrollDivision(menu.tasks.size, GRID_WIDTH) + } + }, { _, _, _ -> }) + + scrollBar.dock = Dock.RIGHT + + frame.addTab(FramePanel.Position.TOP, open = { isPatternView = true }) + frame.addTab(FramePanel.Position.TOP, open = { isPatternView = false }) + + val canvas = object : EditablePanel(this@MatterPanelScreen, frame, width = GRID_WIDTH * AbstractSlotPanel.SIZE) { + init { + dock = Dock.LEFT + } + + override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean { + return scrollBar.mouseScrolledInner(x, y, scroll) + } + } + + for (row in 0 until GRID_HEIGHT) { + val rowCanvas = object : EditablePanel(this@MatterPanelScreen, canvas, height = AbstractSlotPanel.SIZE) { + init { + dock = Dock.TOP + } + + override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean { + return false + } + } + + for (i in 0 until GRID_WIDTH) { + object : AbstractSlotPanel(this@MatterPanelScreen, rowCanvas) { + init { + dock = Dock.LEFT + } + + private val index: Int get() = (scrollBar.scroll + row) * GRID_WIDTH + i + + override fun getItemStack(): ItemStack { + if (isPatternView) { + return menu.patterns.getOrNull(index)?.stack() ?: ItemStack.EMPTY + } else { + return menu.tasks.getOrNull(index)?.let { it.stack(it.required + it.inProgress) } ?: ItemStack.EMPTY + } + } + + override fun getItemStackTooltip(stack: ItemStack): List { + val list = super.getItemStackTooltip(stack).toMutableList() + + if (isPatternView) { + menu.patterns.getOrNull(index)?.let { + list.add(TranslatableComponent( + "otm.item.pattern.research", + String.format("%.2f", it.researchPercent * 100.0) + ).withStyle(ChatFormatting.AQUA)) } + } else { + menu.tasks.getOrNull(index)?.let { + list.add(TranslatableComponent("otm.gui.matter_task.total", it.total).withStyle(ChatFormatting.GRAY)) + list.add(TranslatableComponent("otm.gui.matter_task.required", it.required).withStyle(ChatFormatting.GRAY)) + list.add(TranslatableComponent("otm.gui.matter_task.in_progress", it.inProgress).withStyle(ChatFormatting.GRAY)) + list.add(TranslatableComponent("otm.gui.matter_task.finished", it.finished).withStyle(ChatFormatting.GRAY)) + } + } + + return list + } + + override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { + if (isPatternView) { + menu.patterns.getOrNull(index)?.let(this@MatterPanelScreen::openPattern) + } else { + menu.tasks.getOrNull(index)?.let(this@MatterPanelScreen::openTask) + } + + return true + } + + override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean { + return false + } + } + } + } + + return frame + } + + private fun openTask(task: IReplicationTask<*>) { + val frame = FramePanel.padded(this, null, 170f, 20f, TranslatableComponent("otm.container.matter_panel.task")) + + object : AbstractSlotPanel(this@MatterPanelScreen, frame) { + init { + dock = Dock.LEFT + } + + override fun getItemStack(): ItemStack { + return menu.tasks.firstOrNull { it.id == task.id }?.let { it.stack((it.required + it.inProgress).coerceAtLeast(1)) } ?: task.stack((task.required + task.inProgress).coerceAtLeast(1)) + } + + override fun tick() { + super.tick() + + if (!menu.tasks.any { it.id == task.id }) { + frame.remove() + } + } + } + + ButtonPanel(this@MatterPanelScreen, frame, width = 40f, label = TranslatableComponent("otm.container.matter_panel.close"), onPress = frame::remove).also { + it.dock = Dock.RIGHT + it.dockLeft = 2f + } + + ButtonPanel(this@MatterPanelScreen, frame, width = 80f, label = TranslatableComponent("otm.container.matter_panel.cancel_task"), onPress = { + menu.requestTaskCancel(task.id) + frame.remove() + }).also { + it.dock = Dock.RIGHT + it.dockLeft = 2f + } + + addPanel(frame) + popup(frame) + + frame.toScreenCenter() + } + + private fun openPattern(pattern: IPatternState) { + val frame = FramePanel.padded(this, null, 213f, (ButtonPanel.HEIGHT + 3f) * 4f, TranslatableComponent("otm.container.matter_panel.task")) + + val rowTop = EditablePanel(this, frame, height = ButtonPanel.HEIGHT) + val rowInput = EditablePanel(this, frame, height = ButtonPanel.HEIGHT) + val rowBottom = EditablePanel(this, frame, height = ButtonPanel.HEIGHT) + val rowControls = EditablePanel(this, frame, height = ButtonPanel.HEIGHT) + + rowTop.dock = Dock.TOP + rowTop.dockTop = 3f + rowInput.dock = Dock.TOP + rowInput.dockTop = 3f + rowBottom.dock = Dock.TOP + rowBottom.dockTop = 3f + rowControls.dock = Dock.TOP + rowControls.dockTop = 3f + + object : AbstractSlotPanel(this@MatterPanelScreen, rowInput) { + init { + dock = Dock.LEFT + dockRight = 2f + } + + override fun getItemStack(): ItemStack { + return pattern.stack() + } + + override fun getItemStackTooltip(stack: ItemStack): List { + return super.getItemStackTooltip(stack).toMutableList().also { + it.add(TranslatableComponent( + "otm.item.pattern.research", + String.format("%.2f", pattern.researchPercent * 100.0) + ).withStyle(ChatFormatting.AQUA)) + } + } + + override fun tick() { + super.tick() + + if (!menu.patterns.any { it.id == pattern.id }) { + frame.remove() + } + } + } + + val input = object : EditBoxPanel(this@MatterPanelScreen, rowInput) { + init { + dock = Dock.FILL + } + + override fun configureNew(widget: EditBox, recreation: Boolean) { + super.configureNew(widget, recreation) + widget.setMaxLength(6) + + if (!recreation) { + widget.value = "1" + } + } + + fun increase(amount: Int) { + var value = 1 + + try { + value = getOrCreateWidget().value.toInt() + } catch (_: NumberFormatException) { + } + + if (value == 1 && amount > 0) + getOrCreateWidget().value = amount.toString() + else + getOrCreateWidget().value = 1.coerceAtLeast(99999.coerceAtMost(value + amount)).toString() + } + + fun send() { + var value = 1 + + try { + value = getOrCreateWidget().value.toInt() + } catch (_: NumberFormatException) { + } + + MenuNetworkChannel.sendToServer(ReplicationRequestPacket(pattern.id, value)) + frame.remove() + } + } + + ButtonPanel(this, rowTop, width = 40f, label = TranslatableComponent("otm.container.matter_panel.increase_by", 8), onPress = { input.increase(8) }).also { + it.dock = Dock.RIGHT + it.dockLeft = 2f + } + + ButtonPanel(this, rowTop, width = 40f, label = TranslatableComponent("otm.container.matter_panel.increase_by", 64), onPress = { input.increase(64) }).also { + it.dock = Dock.RIGHT + it.dockLeft = 2f + } + + ButtonPanel(this, rowTop, width = 40f, label = TranslatableComponent("otm.container.matter_panel.increase_by", 256), onPress = { input.increase(256) }).also { + it.dock = Dock.RIGHT + it.dockLeft = 2f + } + + ButtonPanel(this, rowBottom, width = 40f, label = TranslatableComponent("otm.container.matter_panel.decrease_by", 8), onPress = { input.increase(-8) }).also { + it.dock = Dock.RIGHT + it.dockLeft = 2f + } + + ButtonPanel(this, rowBottom, width = 40f, label = TranslatableComponent("otm.container.matter_panel.decrease_by", 64), onPress = { input.increase(-64) }).also { + it.dock = Dock.RIGHT + it.dockLeft = 2f + } + + ButtonPanel(this, rowBottom, width = 40f, label = TranslatableComponent("otm.container.matter_panel.decrease_by", 256), onPress = { input.increase(-256) }).also { + it.dock = Dock.RIGHT + it.dockLeft = 2f + } + + ButtonPanel(this, rowControls, width = 40f, label = TranslatableComponent("otm.container.matter_panel.cancel"), onPress = frame::remove).also { + it.dock = Dock.RIGHT + it.dockLeft = 2f + } + + ButtonPanel(this, rowControls, width = 82f, label = TranslatableComponent("otm.container.matter_panel.send"), onPress = input::send).also { + it.dock = Dock.RIGHT + it.dockLeft = 2f + } + + addPanel(frame) + popup(frame) + + frame.toScreenCenter() + } + + companion object { + const val GRID_HEIGHT = 8 + const val GRID_WIDTH = 9 + } +} 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 e1c89f2c9..b2c5b5f4a 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 @@ -2,6 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.vertex.PoseStack +import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap +import it.unimi.dsi.fastutil.ints.Int2ObjectFunction import net.minecraft.ChatFormatting import net.minecraft.client.gui.Font import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen @@ -14,9 +16,8 @@ import net.minecraftforge.client.event.ContainerScreenEvent.Render.Foreground import net.minecraftforge.common.MinecraftForge import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL13 -import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel -import ru.dbotthepony.mc.otm.client.screen.panels.SlotPanel +import ru.dbotthepony.mc.otm.capability.matteryPlayer +import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.menu.MatteryMenu /** @@ -50,16 +51,108 @@ abstract class MatteryScreen(menu: T, inventory: Inventory, tit val quickCraftingType get() = quickCraftingType val isQuickCrafting get() = isQuickCrafting + private val inventorySlotsRows = Int2ObjectAVLTreeMap() + init { if (menu.playerInventorySlots.isNotEmpty() && menu.autoCreateInventoryFrame) { - inventoryFrame = FramePanel(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH, INVENTORY_FRAME_HEIGHT, inventory.displayName).also(this::addPanel) + if (menu.playerExoSuitSlots.isEmpty()) { + inventoryFrame = FramePanel(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH, INVENTORY_FRAME_HEIGHT, inventory.displayName).also(this::addPanel) - for (slot in menu.playerInventorySlots) { - SlotPanel(this, inventoryFrame, slot, slot.x.toFloat(), slot.y.toFloat()) + val hotbarStrip = EditablePanel(this, inventoryFrame, height = AbstractSlotPanel.SIZE) + hotbarStrip.dock = Dock.BOTTOM + + for (slot in menu.playerHotbarSlots) { + SlotPanel(this, hotbarStrip, slot).also { it.dock = Dock.LEFT } + } + + for (i in 0 .. 2) { + getInventorySlotsRow(i).also { + it.parent = inventoryFrame + it.y = i * AbstractSlotPanel.SIZE + } + } + } else { + inventoryFrame = FramePanel(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH_EXTENDED, INVENTORY_FRAME_HEIGHT, inventory.displayName).also(this::addPanel) + + var slotListCanvas: EditablePanel? = null + + val scrollbar = DiscreteScrollBarPanel(this, inventoryFrame, { ((menu.playerCombinedInventorySlots.size - 27) + 8) / 9 }, { + _, old, new -> + + for (i in old .. old + 2) { + getInventorySlotsRow(i).visible = false + } + + for (i in new .. new + 2) { + getInventorySlotsRow(i).also { + it.visible = true + it.parent = slotListCanvas + it.y = (i - new) * AbstractSlotPanel.SIZE + } + } + + menu.ply.matteryPlayer?.exoSuitMenu?.lastScroll = new + }) + + slotListCanvas = object : EditablePanel(this@MatteryScreen, inventoryFrame, height = AbstractSlotPanel.SIZE * 3f) { + override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean { + scrollbar.mouseScrolledInner(x, y, scroll) + return true + } + } + + slotListCanvas.dock = Dock.TOP + + val hotbarStrip = EditablePanel(this, inventoryFrame, height = AbstractSlotPanel.SIZE) + hotbarStrip.dock = Dock.BOTTOM + + for (slot in menu.playerHotbarSlots) { + SlotPanel(this, hotbarStrip, slot).also { it.dock = Dock.LEFT } + } + + scrollbar.parent = slotListCanvas + scrollbar.dock = Dock.RIGHT + + scrollbar.scroll = menu.ply.matteryPlayer?.exoSuitMenu?.lastScroll ?: 0 + + for (i in scrollbar.scroll .. scrollbar.scroll + 2) { + getInventorySlotsRow(i).also { + it.parent = slotListCanvas + it.y = (i - scrollbar.scroll) * AbstractSlotPanel.SIZE + } + } } } } + protected fun getInventorySlotsRow(index: Int): EditablePanel { + return inventorySlotsRows.computeIfAbsent(index, Int2ObjectFunction { + val canvas = object : EditablePanel(this@MatteryScreen, null, width = AbstractSlotPanel.SIZE * 9f, height = AbstractSlotPanel.SIZE) { + override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean { + return false + } + } + + val offset = it * 9 + + if (menu.playerCombinedInventorySlots.size <= offset) { + return@Int2ObjectFunction canvas + } + + for (i in 0 .. (8).coerceAtMost(menu.playerCombinedInventorySlots.size - offset - 1)) { + val slot = object : SlotPanel(this@MatteryScreen, canvas, menu.playerCombinedInventorySlots[offset + i]) { + override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean { + return false + } + } + + slot.dock = Dock.LEFT + } + + return@Int2ObjectFunction canvas + }) + } + override fun init() { super.init() @@ -102,7 +195,7 @@ abstract class MatteryScreen(menu: T, inventory: Inventory, tit require(indexOf != -1) { "No such panel $panel" } - if (indexOf == panels.size - 1) { + if (indexOf == 0) { return } @@ -354,10 +447,13 @@ abstract class MatteryScreen(menu: T, inventory: Inventory, tit } companion object { - const val DEFAULT_FRAME_WIDTH = 18f * 9f + 16f + const val DEFAULT_FRAME_WIDTH = AbstractSlotPanel.SIZE * 9f + 16f const val DEFAULT_FRAME_HEIGHT = 100f + const val INVENTORY_FRAME_WIDTH = DEFAULT_FRAME_WIDTH - const val INVENTORY_FRAME_HEIGHT = 3f * 18f + 18f + 24f + const val INVENTORY_FRAME_WIDTH_EXTENDED = DEFAULT_FRAME_WIDTH + ScrollBarConstants.WIDTH + 2f + const val INVENTORY_FRAME_HEIGHT = 3f * AbstractSlotPanel.SIZE + AbstractSlotPanel.SIZE + 24f + const val GAUGE_TOP_WITH_SLOT = 17f const val GAUGE_TOP_WITHOUT_SLOT = 26f const val SLOT_TOP_UNDER_GAUGE = 70f diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageBusScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageBusScreen.kt index 342a0dfea..ce186d984 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageBusScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageBusScreen.kt @@ -2,9 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.screen.panels.* -import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.menu.StorageBusMenu diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageExporterScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageExporterScreen.kt index 7ea5b4169..12fadc33e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageExporterScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageExporterScreen.kt @@ -2,9 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.screen.panels.* -import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.menu.StorageExporterMenu diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageImporterScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageImporterScreen.kt index d6aff0902..866f259f6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageImporterScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StorageImporterScreen.kt @@ -2,9 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.screen.panels.* -import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.menu.StorageImporterMenu diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StoragePowerSupplierScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StoragePowerSupplierScreen.kt index 7e0f0d90e..4f0a44c30 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StoragePowerSupplierScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/StoragePowerSupplierScreen.kt @@ -2,10 +2,9 @@ package ru.dbotthepony.mc.otm.client.screen import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory -import ru.dbotthepony.mc.otm.TranslatableComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.screen.panels.* -import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel -import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.HorizontalPowerGaugePanel import ru.dbotthepony.mc.otm.core.formatPower import ru.dbotthepony.mc.otm.menu.StoragePowerSupplierMenu @@ -13,12 +12,32 @@ import ru.dbotthepony.mc.otm.menu.StoragePowerSupplierMenu class StoragePowerSupplierScreen(menu: StoragePowerSupplierMenu, inventory: Inventory, title: Component) : MatteryScreen(menu, inventory, title) { override fun makeMainFrame(): FramePanel { - val frame = super.makeMainFrame()!! + val frame = FramePanel(this, width = 200f, height = 60f, title) - WidePowerGaugePanel(this, frame, menu.powerWidget, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT) - BatterySlotPanel(this, frame, menu.batterySlot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE) + HorizontalPowerGaugePanel(this, frame, menu.powerWidget).also { + it.dock = Dock.BOTTOM + it.dockResize = DockResizeMode.NONE + } + + val topStrip = EditablePanel(this, frame, height = AbstractSlotPanel.SIZE) + + topStrip.dock = Dock.TOP + topStrip.dockTop = 3f + + BatterySlotPanel(this, topStrip, menu.batterySlot).also { + it.dock = Dock.LEFT + it.dockRight = 3f + } + + val labels = EditablePanel(this, topStrip) + + labels.dock = Dock.FILL + + object : Label(this@StoragePowerSupplierScreen, labels) { + init { + dock = Dock.TOP + } - object : Label(this@StoragePowerSupplierScreen, frame, 28f, 17f, width = 140f) { override fun tick() { super.tick() @@ -29,6 +48,21 @@ class StoragePowerSupplierScreen(menu: StoragePowerSupplierMenu, inventory: Inve } } + object : Label(this@StoragePowerSupplierScreen, labels) { + init { + dock = Dock.TOP + } + + override fun tick() { + super.tick() + + text = TranslatableComponent( + "otm.gui.power_supplier.active_nodes", + menu.activeNodes + ) + } + } + return frame } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/AbstractSlotPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/AbstractSlotPanel.kt index b9b59d0b7..04da77a37 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/AbstractSlotPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/AbstractSlotPanel.kt @@ -23,9 +23,8 @@ abstract class AbstractSlotPanel @JvmOverloads constructor( ) : EditablePanel( screen, parent, x, y, width, height ) { - protected open fun renderSlotBackground(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) { - RenderSystem.setShaderTexture(0, WidgetLocation.WIDGETS) - drawTexturedRectAuto(stack, 0f, 0f, 18f, 18f, 0f, 96f, 256f, 256f) + protected open fun renderSlotBackground(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) { + SLOT_BACKGROUND.render(stack, width = width, height = height) } protected open fun renderRegular(stack: PoseStack, itemstack: ItemStack, count_override: String? = null) { @@ -119,10 +118,9 @@ abstract class AbstractSlotPanel @JvmOverloads constructor( } companion object { - @JvmField val SLOT_HIGHLIGHT = RGBAColor(255, 255, 255, 100) - @JvmField val SLOT_HIGHLIGHT_DRAG = RGBAColor(200, 200, 200, 150) const val SIZE = 18f + val SLOT_BACKGROUND = WidgetLocation.WIDGETS.element(0f, 0f, SIZE, SIZE) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt index b07c2e14a..7a48b5ec2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt @@ -5,15 +5,13 @@ import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.ChatFormatting import net.minecraft.client.gui.components.Button import net.minecraft.client.gui.components.Button.OnPress -import net.minecraft.client.resources.sounds.SimpleSoundInstance import net.minecraft.network.chat.Component -import net.minecraft.sounds.SoundEvents -import ru.dbotthepony.mc.otm.TextComponent -import ru.dbotthepony.mc.otm.client.minecraft +import ru.dbotthepony.mc.otm.client.playGuiClickSound +import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.client.screen.MatteryScreen -import ru.dbotthepony.mc.otm.next -import ru.dbotthepony.mc.otm.prev +import ru.dbotthepony.mc.otm.core.next +import ru.dbotthepony.mc.otm.core.prev import java.util.* import kotlin.collections.ArrayList import kotlin.reflect.KMutableProperty0 @@ -24,10 +22,22 @@ open class ButtonPanel( x: Float = 0f, y: Float = 0f, width: Float = 40f, - height: Float = 20f, + height: Float = HEIGHT, label: Component ) : MinecraftWidgetPanel