diff --git a/.gitignore b/.gitignore index 9cf9fd7d..d5f11567 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # User-specific stuff .idea/ +.kotlin/ *.iml *.ipr diff --git a/build.gradle.kts b/build.gradle.kts index 88638c94..3594b12c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ import org.jetbrains.gradle.ext.Gradle import org.jetbrains.gradle.ext.RunConfigurationContainer +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import java.util.* plugins { @@ -92,6 +93,18 @@ tasks.compileTestJava.configure { } } +tasks.compileKotlin.configure { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) + } +} + +tasks.compileTestKotlin.configure { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) + } +} + tasks.javadoc.configure { // No need for JavaDoc. actions = Collections.emptyList() @@ -167,7 +180,7 @@ repositories { } maven { name = "GTNH Maven" - url = uri("http://jenkins.usrv.eu:8081/nexus/content/groups/public/") + url = uri("https://nexus.gtnewhorizons.com/repository/public/") isAllowInsecureProtocol = true } mavenCentral() @@ -273,13 +286,10 @@ dependencies { compileOnly(rfg.deobf("curse.maven:endercore-231868:4671384")) compileOnly(rfg.deobf("curse.maven:ender-io-64578:4674244")) compileOnly(rfg.deobf("curse.maven:more-electric-tools-366298:3491973")) - compileOnly(rfg.deobf("curse.maven:brandonscore-231382:3051539")) - compileOnly(rfg.deobf("curse.maven:draconicevolution-223565:3051542")) implementation(rfg.deobf("curse.maven:extrabotany-299086:3112313")) implementation(rfg.deobf("curse.maven:libnine-322344:3509087")) implementation(rfg.deobf("curse.maven:lazy-ae2-322347:3254160")) compileOnly(rfg.deobf("curse.maven:better-chat-363860:3048407")) - compileOnly(rfg.deobf("curse.maven:ae2-fluid-crafting-rework-623955:5237484")) compileOnly(rfg.deobf("curse.maven:lunatriuscore-225605:2489549")) compileOnly(rfg.deobf("curse.maven:immersive-engineering-231951:2974106")) compileOnly(rfg.deobf("curse.maven:immersive-petroleum-268250:3382321")) @@ -306,9 +316,11 @@ dependencies { implementation(rfg.deobf("curse.maven:packagedauto-308380:6312996")) compileOnly(rfg.deobf("curse.maven:libvulpes-236541:3801015")) compileOnly(rfg.deobf("curse.maven:advanced-rocketry-236542:4671856")) - implementation(rfg.deobf("curse.maven:random-complement-1198138:7133485")) + implementation(rfg.deobf("curse.maven:random-complement-1198138:7155516")) implementation(rfg.deobf("curse.maven:modular-routers-250294:2954953")) implementation(rfg.deobf("curse.maven:actually-additions-228404:3117927")) + implementation(rfg.deobf("curse.maven:brandons-core-231382:3408276")) + implementation(rfg.deobf("curse.maven:draconic-evolution-223565:3431261")) } // Publishing to a Maven repository diff --git a/settings.gradle.kts b/settings.gradle.kts index b73ee3a0..634dedcb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,7 +3,7 @@ pluginManagement { maven { // RetroFuturaGradle name = "GTNH Maven" - url = uri("http://jenkins.usrv.eu:8081/nexus/content/groups/public/") + url = uri("https://nexus.gtnewhorizons.com/repository/public/") isAllowInsecureProtocol = true mavenContent { includeGroup("com.gtnewhorizons") diff --git a/src/main/java/github/kasuminova/mmce/client/gui/widget/DragBar.java b/src/main/java/github/kasuminova/mmce/client/gui/widget/DragBar.java index 50ad39a7..219ce3b5 100644 --- a/src/main/java/github/kasuminova/mmce/client/gui/widget/DragBar.java +++ b/src/main/java/github/kasuminova/mmce/client/gui/widget/DragBar.java @@ -8,10 +8,16 @@ import github.kasuminova.mmce.common.util.DataReference; import github.kasuminova.novaeng.NovaEngineeringCore; import github.kasuminova.novaeng.common.crafttweaker.util.NovaEngUtils; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; +@Accessors(chain = true) +@Setter +@Getter @SuppressWarnings("unused") public class DragBar extends DynamicWidget { @@ -203,192 +209,8 @@ public int getWidth() { return super.getWidth() + paddingHorizontal * 2; } - // Getter / Setters - - public DragBarButton getDragBarButton() { - return dragBarButton; - } - - public int getPaddingHorizontal() { - return paddingHorizontal; - } - - public DragBar setPaddingHorizontal(final int paddingHorizontal) { - this.paddingHorizontal = paddingHorizontal; - return this; - } - - public ResourceLocation getTexLocation() { - return texLocation; - } - - public DragBar setTexLocation(final ResourceLocation texLocation) { - this.texLocation = texLocation; - return this; - } - - public int getBarHeight() { - return barHeight; - } - - public DragBar setBarHeight(final int barHeight) { - this.barHeight = barHeight; - return this; - } - - public int getBarLeftTexOffsetX() { - return barLeftTexOffsetX; - } - - public DragBar setBarLeftTexOffsetX(final int barLeftTexOffsetX) { - this.barLeftTexOffsetX = barLeftTexOffsetX; - return this; - } - - public int getBarLeftTexOffsetY() { - return barLeftTexOffsetY; - } - - public DragBar setBarLeftTexOffsetY(final int barLeftTexOffsetY) { - this.barLeftTexOffsetY = barLeftTexOffsetY; - return this; - } - - public int getBarLeftTexOffsetXFilled() { - return barLeftTexOffsetXFilled; - } - - public DragBar setBarLeftTexOffsetXFilled(final int barLeftTexOffsetXFilled) { - this.barLeftTexOffsetXFilled = barLeftTexOffsetXFilled; - return this; - } - - public int getBarLeftTexOffsetYFilled() { - return barLeftTexOffsetYFilled; - } - - public DragBar setBarLeftTexOffsetYFilled(final int barLeftTexOffsetYFilled) { - this.barLeftTexOffsetYFilled = barLeftTexOffsetYFilled; - return this; - } - - public int getBarLeftTexWidth() { - return barLeftTexWidth; - } - - public DragBar setBarLeftTexWidth(final int barLeftTexWidth) { - this.barLeftTexWidth = barLeftTexWidth; - return this; - } - - public int getBarMidTexOffsetX() { - return barMidTexOffsetX; - } - - public DragBar setBarMidTexOffsetX(final int barMidTexOffsetX) { - this.barMidTexOffsetX = barMidTexOffsetX; - return this; - } - - public int getBarMidTexOffsetY() { - return barMidTexOffsetY; - } - - public DragBar setBarMidTexOffsetY(final int barMidTexOffsetY) { - this.barMidTexOffsetY = barMidTexOffsetY; - return this; - } - - public int getBarMidTexOffsetXFilled() { - return barMidTexOffsetXFilled; - } - - public DragBar setBarMidTexOffsetXFilled(final int barMidTexOffsetXFilled) { - this.barMidTexOffsetXFilled = barMidTexOffsetXFilled; - return this; - } - - public int getBarMidTexOffsetYFilled() { - return barMidTexOffsetYFilled; - } - - public DragBar setBarMidTexOffsetYFilled(final int barMidTexOffsetYFilled) { - this.barMidTexOffsetYFilled = barMidTexOffsetYFilled; - return this; - } - - public int getBarRightTexOffsetX() { - return barRightTexOffsetX; - } - - public DragBar setBarRightTexOffsetX(final int barRightTexOffsetX) { - this.barRightTexOffsetX = barRightTexOffsetX; - return this; - } - - public int getBarRightTexOffsetY() { - return barRightTexOffsetY; - } - - public DragBar setBarRightTexOffsetY(final int barRightTexOffsetY) { - this.barRightTexOffsetY = barRightTexOffsetY; - return this; - } - - public int getBarRightTexOffsetXFilled() { - return barRightTexOffsetXFilled; - } - - public DragBar setBarRightTexOffsetXFilled(final int barRightTexOffsetXFilled) { - this.barRightTexOffsetXFilled = barRightTexOffsetXFilled; - return this; - } - - public int getBarRightTexOffsetYFilled() { - return barRightTexOffsetYFilled; - } - - public DragBar setBarRightTexOffsetYFilled(final int barRightTexOffsetYFilled) { - this.barRightTexOffsetYFilled = barRightTexOffsetYFilled; - return this; - } - - public int getBarRightTexWidth() { - return barRightTexWidth; - } - - public DragBar setBarRightTexWidth(final int barRightTexWidth) { - this.barRightTexWidth = barRightTexWidth; - return this; - } - - public DataReference getValue() { - return value; - } - - public DragBar setValue(final DataReference value) { - this.value = value; - return this; - } - - public DataReference getMin() { - return min; - } - - public DragBar setMin(final DataReference min) { - this.min = min; - return this; - } - - public DataReference getMax() { - return max; - } - - public DragBar setMax(final DataReference max) { - this.max = max; - return this; - } - + @Accessors(chain = true) + @Setter public class DragBarButton extends DynamicWidget { public static final int DEFAULT_BUTTON_HEIGHT = 9; @@ -408,36 +230,54 @@ public class DragBarButton extends DynamicWidget { public static final float MOUSE_OVER_DARK_VALUE = 0.15F; public static final float MOUSE_DOWN_DARK_VALUE = 0.3F; + @Getter protected ResourceLocation texLocation = DEFAULT_TEX_RES; protected float width = 0; protected float height; + @Getter protected int buttonLeftTexOffsetX = DEFAULT_BUTTON_LEFT_TEX_OFFSET_X; + @Getter protected int buttonLeftTexOffsetY = DEFAULT_BUTTON_LEFT_TEX_OFFSET_Y; + @Getter protected int buttonLeftTexWidth = DEFAULT_BUTTON_LEFT_TEX_WIDTH; + @Getter protected int buttonMidTexOffsetX = DEFAULT_BUTTON_MID_TEX_OFFSET_X; + @Getter protected int buttonMidTexOffsetY = DEFAULT_BUTTON_MID_TEX_OFFSET_Y; + @Getter protected int buttonRightTexOffsetX = DEFAULT_BUTTON_RIGHT_TEX_OFFSET_X; + @Getter protected int buttonRightTexOffsetY = DEFAULT_BUTTON_RIGHT_TEX_OFFSET_Y; + @Getter protected int buttonRightTexWidth = DEFAULT_BUTTON_RIGHT_TEX_WIDTH; + @Getter protected int animationDuration = DEFAULT_ANIMATION_DURATION; protected double cachedValue; + @Getter protected long expandAnimationStartTime = 0; + @Getter protected boolean expandAnimationStarted = false; + @Getter protected float expandedWidth = 0; + @Getter protected float lastExpandedWidth = 0; + @Getter protected long lastColorUpdateTime = 0; + @Getter protected float darkValue = 0; + @Getter protected boolean mouseOver = false; + @Getter protected boolean mouseDown = false; public DragBarButton() { @@ -603,163 +443,91 @@ protected int getContentWidth(final WidgetGui widgetGui) { return widgetGui.getGui().mc.fontRenderer.getStringWidth(formattedValue); } - public ResourceLocation getTexLocation() { - return texLocation; - } - public DragBarButton setTexLocation(final ResourceLocation texLocation) { this.texLocation = texLocation; return this; } - public int getButtonLeftTexOffsetX() { - return buttonLeftTexOffsetX; - } - public DragBarButton setButtonLeftTexOffsetX(final int buttonLeftTexOffsetX) { this.buttonLeftTexOffsetX = buttonLeftTexOffsetX; return this; } - public int getButtonLeftTexOffsetY() { - return buttonLeftTexOffsetY; - } - public DragBarButton setButtonLeftTexOffsetY(final int buttonLeftTexOffsetY) { this.buttonLeftTexOffsetY = buttonLeftTexOffsetY; return this; } - public int getButtonLeftTexWidth() { - return buttonLeftTexWidth; - } - public DragBarButton setButtonLeftTexWidth(final int buttonLeftTexWidth) { this.buttonLeftTexWidth = buttonLeftTexWidth; return this; } - public int getButtonMidTexOffsetX() { - return buttonMidTexOffsetX; - } - public DragBarButton setButtonMidTexOffsetX(final int buttonMidTexOffsetX) { this.buttonMidTexOffsetX = buttonMidTexOffsetX; return this; } - public int getButtonMidTexOffsetY() { - return buttonMidTexOffsetY; - } - public DragBarButton setButtonMidTexOffsetY(final int buttonMidTexOffsetY) { this.buttonMidTexOffsetY = buttonMidTexOffsetY; return this; } - public int getButtonRightTexOffsetX() { - return buttonRightTexOffsetX; - } - public DragBarButton setButtonRightTexOffsetX(final int buttonRightTexOffsetX) { this.buttonRightTexOffsetX = buttonRightTexOffsetX; return this; } - public int getButtonRightTexOffsetY() { - return buttonRightTexOffsetY; - } - public DragBarButton setButtonRightTexOffsetY(final int buttonRightTexOffsetY) { this.buttonRightTexOffsetY = buttonRightTexOffsetY; return this; } - public int getButtonRightTexWidth() { - return buttonRightTexWidth; - } - public DragBarButton setButtonRightTexWidth(final int buttonRightTexWidth) { this.buttonRightTexWidth = buttonRightTexWidth; return this; } - public int getAnimationDuration() { - return animationDuration; - } - public DragBarButton setAnimationDuration(final int animationDuration) { this.animationDuration = animationDuration; return this; } - public long getExpandAnimationStartTime() { - return expandAnimationStartTime; - } - public DragBarButton setExpandAnimationStartTime(final long expandAnimationStartTime) { this.expandAnimationStartTime = expandAnimationStartTime; return this; } - public boolean isExpandAnimationStarted() { - return expandAnimationStarted; - } - public DragBarButton setExpandAnimationStarted(final boolean expandAnimationStarted) { this.expandAnimationStarted = expandAnimationStarted; return this; } - public float getExpandedWidth() { - return expandedWidth; - } - public DragBarButton setExpandedWidth(final float expandedWidth) { this.expandedWidth = expandedWidth; return this; } - public float getLastExpandedWidth() { - return lastExpandedWidth; - } - public DragBarButton setLastExpandedWidth(final float lastExpandedWidth) { this.lastExpandedWidth = lastExpandedWidth; return this; } - public long getLastColorUpdateTime() { - return lastColorUpdateTime; - } - public DragBarButton setLastColorUpdateTime(final long lastColorUpdateTime) { this.lastColorUpdateTime = lastColorUpdateTime; return this; } - public float getDarkValue() { - return darkValue; - } - public DragBarButton setDarkValue(final float darkValue) { this.darkValue = darkValue; return this; } - public boolean isMouseOver() { - return mouseOver; - } - public DragBarButton setMouseOver(final boolean mouseOver) { this.mouseOver = mouseOver; return this; } - public boolean isMouseDown() { - return mouseDown; - } - public DragBarButton setMouseDown(final boolean mouseDown) { this.mouseDown = mouseDown; return this; diff --git a/src/main/java/github/kasuminova/mmce/common/util/DataReference.java b/src/main/java/github/kasuminova/mmce/common/util/DataReference.java index d997f462..ce242b89 100644 --- a/src/main/java/github/kasuminova/mmce/common/util/DataReference.java +++ b/src/main/java/github/kasuminova/mmce/common/util/DataReference.java @@ -1,5 +1,10 @@ package github.kasuminova.mmce.common.util; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter public class DataReference { private T value; @@ -8,11 +13,4 @@ public DataReference(final T value) { this.value = value; } - public T getValue() { - return value; - } - - public void setValue(final T value) { - this.value = value; - } } diff --git a/src/main/java/github/kasuminova/novaeng/NovaEngCoreConfig.java b/src/main/java/github/kasuminova/novaeng/NovaEngCoreConfig.java new file mode 100644 index 00000000..f287e7f9 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/NovaEngCoreConfig.java @@ -0,0 +1,74 @@ +package github.kasuminova.novaeng; + +import com.cleanroommc.configanytime.ConfigAnytime; +import net.minecraftforge.common.config.Config; +import net.minecraftforge.common.config.ConfigManager; +import net.minecraftforge.fml.client.event.ConfigChangedEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; + +import java.util.Objects; + +@Mod.EventBusSubscriber(modid = NovaEngineeringCore.MOD_ID, value = Side.CLIENT) +@Config(modid = NovaEngineeringCore.MOD_ID, name = NovaEngineeringCore.MOD_ID) +public class NovaEngCoreConfig { + + @Config.Name("Client") + public static Client CLIENT = new Client(); + + @Config.Name("Server") + public static Server SERVER = new Server(); + + @Config.Name("MachineAssemblyTool") + public static MachineAssemblyTool MACHINE_ASSEMBLY_TOOL = new MachineAssemblyTool(); + + @Config.RequiresMcRestart + @Config.Name("javaCheck") + public static boolean javaCheck = true; + + static { + ConfigAnytime.register(NovaEngCoreConfig.class); + } + + @SubscribeEvent + public static void onConfigChanged(ConfigChangedEvent.OnConfigChangedEvent event) { + if (Objects.equals(event.getModID(), NovaEngineeringCore.MOD_ID)) { + ConfigManager.sync(NovaEngineeringCore.MOD_ID, Config.Type.INSTANCE); + } + } + + public static class Client { + @Config.RequiresMcRestart + @Config.Name("EnableNovaEngTitle") + public boolean enableNovaEngTitle = true; + + @Config.RequiresMcRestart + @Config.Name("爆炸") + public boolean piece = false; + } + + public static class Server { + @Config.RequiresMcRestart + @Config.Name("ForceChunkHandler") + public boolean forceChunkHandler = true; + + @Config.RequiresMcRestart + @Config.Name("SpecialMachine") + public boolean specialMachine = true; + + @Config.RequiresMcRestart + @Config.Name("bot") + public boolean bot = true; + } + + public static class MachineAssemblyTool { + @Config.Name("BuildQuantity") + @Config.RangeInt(min = 1, max = 1000) + public int buildQuantity = 100; + + @Config.Name("BuildSpeed") + @Config.RangeInt(min = 1, max = 1000) + public int buildSpeed = 20; + } +} diff --git a/src/main/java/github/kasuminova/novaeng/NovaEngCoreConfig.kt b/src/main/java/github/kasuminova/novaeng/NovaEngCoreConfig.kt deleted file mode 100644 index 9f3c8dbd..00000000 --- a/src/main/java/github/kasuminova/novaeng/NovaEngCoreConfig.kt +++ /dev/null @@ -1,81 +0,0 @@ -package github.kasuminova.novaeng - -import com.cleanroommc.configanytime.ConfigAnytime -import net.minecraftforge.common.config.Config -import net.minecraftforge.common.config.ConfigManager -import net.minecraftforge.fml.client.event.ConfigChangedEvent -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -class NovaEngCoreConfig { - - /* - 必须在最后加载。 - */ - companion object { - @JvmField - @Config.Name("Client") - val CLIENT = Client() - @JvmField - @Config.Name("Server") - val SERVER = Server() - @JvmField - @Config.Name("MachineAssemblyTool") - val MACHINE_ASSEMBLY_TOOL = MachineAssemblyTool() - @JvmField - @Config.RequiresMcRestart - @Config.Name("javaCheck") - var javaCheck = true - - init { - ConfigAnytime.register(Companion::class.java) - } - } - - @SubscribeEvent - fun onConfigChanged(event: ConfigChangedEvent.OnConfigChangedEvent) { - if (event.modID == NovaEngineeringCore.MOD_ID) { - ConfigManager.sync(NovaEngineeringCore.MOD_ID, Config.Type.INSTANCE) - } - } - - class Client { - @JvmField - @Config.RequiresMcRestart - @Config.Name("EnableNovaEngTitle") - var enableNovaEngTitle = true - - @JvmField - @Config.RequiresMcRestart - @Config.Name("爆炸") - var piece = false - } - - class Server { - @JvmField - @Config.RequiresMcRestart - @Config.Name("ForceChunkHandler") - var forceChunkHandler = true - - @JvmField - @Config.RequiresMcRestart - @Config.Name("SpecialMachine") - var specialMachine = true - - @JvmField - @Config.RequiresMcRestart - @Config.Name("bot") - var bot = true - } - - class MachineAssemblyTool { - @JvmField - @Config.Name("BuildQuantity") - @Config.RangeInt(min = 1, max = 1000) - var buildQuantity = 60 - - @JvmField - @Config.Name("BuildSpeed") - @Config.RangeInt(min = 1, max = 1000) - var buildSpeed = 20 - } -} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/NovaEngineeringCore.java b/src/main/java/github/kasuminova/novaeng/NovaEngineeringCore.java index 41ea794c..acc19376 100644 --- a/src/main/java/github/kasuminova/novaeng/NovaEngineeringCore.java +++ b/src/main/java/github/kasuminova/novaeng/NovaEngineeringCore.java @@ -7,6 +7,7 @@ import github.kasuminova.novaeng.common.handler.WorldLoadedHandler; import github.kasuminova.novaeng.common.network.ItemDisplayPkt; import github.kasuminova.novaeng.common.network.ParallelNetworkManager; +import github.kasuminova.novaeng.common.network.PktAutoCraftConfirm; import github.kasuminova.novaeng.common.network.PktCellDriveStatusUpdate; import github.kasuminova.novaeng.common.network.PktECalculatorGUIData; import github.kasuminova.novaeng.common.network.PktEFabricatorGUIAction; @@ -136,6 +137,7 @@ public void preInit(FMLPreInitializationEvent event) { NET_CHANNEL.registerMessage(PktCProfilerReply.class, PktCProfilerReply.class, start++, Side.SERVER); NET_CHANNEL.registerMessage(PktGeocentricDrillControl.class, PktGeocentricDrillControl.class, start++, Side.SERVER); NET_CHANNEL.registerMessage(ItemDisplayPkt.class, ItemDisplayPkt.class, start++, Side.SERVER); + NET_CHANNEL.registerMessage(PktAutoCraftConfirm.class, PktAutoCraftConfirm.class, start++, Side.SERVER); proxy.preInit(); } diff --git a/src/main/java/github/kasuminova/novaeng/client/ClientProxy.java b/src/main/java/github/kasuminova/novaeng/client/ClientProxy.java index d8854093..e7012c96 100644 --- a/src/main/java/github/kasuminova/novaeng/client/ClientProxy.java +++ b/src/main/java/github/kasuminova/novaeng/client/ClientProxy.java @@ -1,6 +1,10 @@ package github.kasuminova.novaeng.client; +import appeng.api.features.IWirelessTermHandler; +import appeng.helpers.WirelessTerminalGuiObject; +import baubles.api.BaublesApi; import github.kasuminova.mmce.client.renderer.MachineControllerRenderer; +import github.kasuminova.novaeng.NovaEngCoreConfig; import github.kasuminova.novaeng.NovaEngineeringCore; import github.kasuminova.novaeng.client.book.BookTransformerAppendModifiers; import github.kasuminova.novaeng.client.gui.GuiECalculatorController; @@ -10,18 +14,20 @@ import github.kasuminova.novaeng.client.gui.GuiEStorageController; import github.kasuminova.novaeng.client.gui.GuiGeocentricDrill; import github.kasuminova.novaeng.client.gui.GuiHyperNetTerminal; +import github.kasuminova.novaeng.client.gui.GuiMachineAssemblyTool; import github.kasuminova.novaeng.client.gui.GuiModularServerAssembler; +import github.kasuminova.novaeng.client.gui.GuiNEWCraftConfirm; import github.kasuminova.novaeng.client.gui.GuiSingularityCore; import github.kasuminova.novaeng.client.handler.BlockAngelRendererHandler; import github.kasuminova.novaeng.client.handler.ClientEventHandler; import github.kasuminova.novaeng.client.handler.HyperNetClientEventHandler; +import github.kasuminova.novaeng.client.handler.MachineAssemblyHandlerClient; import github.kasuminova.novaeng.client.model.raw_ore.RawOreModelLoader; import github.kasuminova.novaeng.client.util.ExJEI; import github.kasuminova.novaeng.client.util.TitleUtils; import github.kasuminova.novaeng.common.CommonProxy; import github.kasuminova.novaeng.common.command.CommandPacketProfiler; import github.kasuminova.novaeng.common.command.ExportResearchDataToJson; -import github.kasuminova.novaeng.NovaEngCoreConfig; import github.kasuminova.novaeng.common.item.ItemRawOre; import github.kasuminova.novaeng.common.registry.RegistryBlocks; import github.kasuminova.novaeng.common.registry.RegistryItems; @@ -85,11 +91,11 @@ @Mod.EventBusSubscriber(Side.CLIENT) public class ClientProxy extends CommonProxy { - @Getter - private static List itemDisplayTooltip; private static final Object2IntMap colorCache = new Object2IntOpenHashMap<>(); public static List items = new ObjectArrayList<>(); public static List blocks = new ObjectArrayList<>(); + @Getter + private static List itemDisplayTooltip; static { colorCache.defaultReturnValue(-1); @@ -172,6 +178,7 @@ public void preInit() { MinecraftForge.EVENT_BUS.register(HyperNetClientEventHandler.INSTANCE); MinecraftForge.EVENT_BUS.register(ClientEventHandler.INSTANCE); MinecraftForge.EVENT_BUS.register(BlockAngelRendererHandler.INSTANCE); + MinecraftForge.EVENT_BUS.register(MachineAssemblyHandlerClient.INSTANCE); itemDisplayTooltip = ObjectLists.singleton(I18n.format("key.novaeng.item_display.tooltip", "Ctrl + L")); @@ -248,8 +255,8 @@ public void onModelRegister(ModelRegistryEvent event) { @Nullable @Override - public Object getClientGuiElement(final int ID, final EntityPlayer player, final World world, final int x, final int y, final int z) { - GuiType type = GuiType.values()[MathHelper.clamp(ID, 0, GuiType.values().length - 1)]; + public Object getClientGuiElement(final int id, final EntityPlayer player, final World world, final int x, final int y, final int z) { + GuiType type = GuiType.values()[MathHelper.clamp(id, 0, GuiType.values().length - 1)]; Class required = type.requiredTileEntity; TileEntity present = null; if (required != null) { @@ -272,6 +279,15 @@ public Object getClientGuiElement(final int ID, final EntityPlayer player, final case EFABRICATOR_PATTERN_BUS -> new GuiEFabricatorPatternBus((EFabricatorPatternBus) present, player); case GEOCENTRIC_DRILL_CONTROLLER -> new GuiGeocentricDrill((GeocentricDrillController) present, player); case ECALCULATOR_CONTROLLER -> new GuiECalculatorController((ECalculatorController) present, player); + case AUTO_CRAFTGUI -> { + var stack = y == 1 ? BaublesApi.getBaublesHandler(player).getStackInSlot(x) + : player.inventory.getStackInSlot(x); + if (stack.getItem() instanceof IWirelessTermHandler wt) { + yield new GuiNEWCraftConfirm(player.inventory, + new WirelessTerminalGuiObject(wt, stack, player, player.world, x, y, Integer.MIN_VALUE)); + } else yield null; + } + case MACHINE_ASSEMBLY_TOOL -> new GuiMachineAssemblyTool(player); }; } diff --git a/src/main/java/github/kasuminova/novaeng/client/book/BookTransformerAppendModifiers.java b/src/main/java/github/kasuminova/novaeng/client/book/BookTransformerAppendModifiers.java index d3acb6fb..8c37f855 100644 --- a/src/main/java/github/kasuminova/novaeng/client/book/BookTransformerAppendModifiers.java +++ b/src/main/java/github/kasuminova/novaeng/client/book/BookTransformerAppendModifiers.java @@ -15,8 +15,8 @@ // adapted from Tinkers' MEMES BookTransformerAppendModifiers public class BookTransformerAppendModifiers extends SectionTransformer { - public static BookTransformerAppendModifiers INSTANCE_FALSE = new BookTransformerAppendModifiers(new FileRepository("tconstruct:book"), false, Register.TRAITREGISTER.modifierTraitsF); - public static BookTransformerAppendModifiers INSTANCE_TRUE = new BookTransformerAppendModifiers(new FileRepository("tconstruct:book"), true, Register.TRAITREGISTER.modifierTraitsT); + public static BookTransformerAppendModifiers INSTANCE_FALSE = new BookTransformerAppendModifiers(new FileRepository("tconstruct:book"), false, Register.INSTANCE.getModifierTraitsF()); + public static BookTransformerAppendModifiers INSTANCE_TRUE = new BookTransformerAppendModifiers(new FileRepository("tconstruct:book"), true, Register.INSTANCE.getModifierTraitsT()); private final BookRepository source; private final boolean armour; private final List modCollector; diff --git a/src/main/java/github/kasuminova/novaeng/client/gui/GuiMachineAssemblyTool.kt b/src/main/java/github/kasuminova/novaeng/client/gui/GuiMachineAssemblyTool.kt new file mode 100644 index 00000000..0f56a082 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/client/gui/GuiMachineAssemblyTool.kt @@ -0,0 +1,19 @@ +package github.kasuminova.novaeng.client.gui + +import com.brandon3055.brandonscore.inventory.PlayerSlot +import com.brandon3055.draconicevolution.client.gui.toolconfig.GuiConfigureTool +import com.brandon3055.draconicevolution.client.gui.toolconfig.GuiToolConfig +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.util.EnumHand + +class GuiMachineAssemblyTool(player: EntityPlayer): GuiConfigureTool( + GuiToolConfig(player),player,player.getHeldItem(EnumHand.MAIN_HAND), + PlayerSlot(player.inventory.currentItem, PlayerSlot.EnumInvCategory.MAIN) +) { + + override fun keyTyped(typedChar: Char, keyCode: Int) { + if (keyCode == 1 || this.mc.gameSettings.keyBindInventory.isActiveAndMatches(keyCode)) { + this.mc.player.closeScreen() + } + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/client/gui/GuiNEWCraftConfirm.kt b/src/main/java/github/kasuminova/novaeng/client/gui/GuiNEWCraftConfirm.kt new file mode 100644 index 00000000..428b0adf --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/client/gui/GuiNEWCraftConfirm.kt @@ -0,0 +1,42 @@ +package github.kasuminova.novaeng.client.gui + +import appeng.client.gui.implementations.GuiCraftConfirm +import appeng.helpers.WirelessTerminalGuiObject +import com.circulation.random_complement.client.RCGuiCraftConfirm +import github.kasuminova.novaeng.NovaEngineeringCore +import github.kasuminova.novaeng.common.network.PktAutoCraftConfirm +import github.kasuminova.novaeng.mixin.ae2.AccessorGuiCraftConfirm +import java.io.IOException +import net.minecraft.client.gui.GuiButton +import net.minecraft.entity.player.InventoryPlayer + +open class GuiNEWCraftConfirm(ip: InventoryPlayer, te: WirelessTerminalGuiObject) : GuiCraftConfirm(ip, te) { + + var cancel: GuiButton? = null + var start: GuiButton? = null + val utils = this as AccessorGuiCraftConfirm + + @Suppress("CAST_NEVER_SUCCEEDS") + override fun initGui() { + super.initGui() + cancel = utils.`n$getCancel`() + start = utils.`n$getStart`() + } + + @Throws(IOException::class) + override fun actionPerformed(btn: GuiButton) { + if (btn == cancel) { + if (this is RCGuiCraftConfirm && isShiftKeyDown()) { + `rc$addMissBookmark`() + } + NovaEngineeringCore.NET_CHANNEL.sendToServer(PktAutoCraftConfirm()) + this.mc.player.closeScreenAndDropStack() + return + } + super.actionPerformed(btn) + if (btn == start) { + this.mc.player.closeScreenAndDropStack() + } + } + +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/client/handler/ClientEventHandler.java b/src/main/java/github/kasuminova/novaeng/client/handler/ClientEventHandler.java index 88c68a8f..f5534fba 100644 --- a/src/main/java/github/kasuminova/novaeng/client/handler/ClientEventHandler.java +++ b/src/main/java/github/kasuminova/novaeng/client/handler/ClientEventHandler.java @@ -1,8 +1,8 @@ package github.kasuminova.novaeng.client.handler; +import github.kasuminova.novaeng.NovaEngCoreConfig; import github.kasuminova.novaeng.NovaEngineeringCore; import github.kasuminova.novaeng.client.util.TitleUtils; -import github.kasuminova.novaeng.NovaEngCoreConfig; import github.kasuminova.novaeng.common.profiler.CPacketProfiler; import github.kasuminova.novaeng.common.profiler.TEUpdatePacketProfiler; import github.kasuminova.novaeng.mixin.minecraft.AccessorParticleManager; diff --git a/src/main/java/github/kasuminova/novaeng/client/handler/ItemDisplayHandler.java b/src/main/java/github/kasuminova/novaeng/client/handler/ItemDisplayHandler.java deleted file mode 100644 index 2d099081..00000000 --- a/src/main/java/github/kasuminova/novaeng/client/handler/ItemDisplayHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package github.kasuminova.novaeng.client.handler; - -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -@SideOnly(Side.CLIENT) -public class ItemDisplayHandler { - -// @SubscribeEvent(priority = EventPriority.HIGHEST) -// public void onInputEvent(GuiScreenEvent.KeyboardInputEvent.Pre event) { -// var mc = Minecraft.getMinecraft(); -// if (mc.currentScreen instanceof GuiContainer gui) { -// int eventKey = Keyboard.getEventKey(); -// if (GuiScreen.isCtrlKeyDown() && Keyboard.KEY_L == eventKey && Keyboard.isKeyDown(eventKey)) { -// var slot = gui.getSlotUnderMouse(); -// if (slot != null) { -// NovaEngineeringCore.NET_CHANNEL.sendToServer(new ItemDisplayPkt(slot.getStack(), mc.player)); -// } -// } -// } -// } - -} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/client/handler/MachineAssemblyHandlerClient.kt b/src/main/java/github/kasuminova/novaeng/client/handler/MachineAssemblyHandlerClient.kt new file mode 100644 index 00000000..ff2a432f --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/client/handler/MachineAssemblyHandlerClient.kt @@ -0,0 +1,91 @@ +package github.kasuminova.novaeng.client.handler + +import github.kasuminova.novaeng.client.util.NEWBlockArrayPreviewRenderHelper +import github.kasuminova.novaeng.common.item.ItemMachineAssemblyTool +import github.kasuminova.novaeng.common.util.NEWMachineAssemblyManager +import net.minecraft.client.Minecraft +import net.minecraft.client.resources.I18n +import net.minecraft.item.ItemBlock +import net.minecraft.item.ItemStack +import net.minecraftforge.client.event.MouseEvent +import net.minecraftforge.client.event.RenderWorldLastEvent +import net.minecraftforge.event.entity.player.ItemTooltipEvent +import net.minecraftforge.event.world.WorldEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent +import net.minecraftforge.fml.common.network.FMLNetworkEvent +import net.minecraftforge.fml.relauncher.Side +import net.minecraftforge.fml.relauncher.SideOnly +import org.lwjgl.input.Mouse + +@SideOnly(Side.CLIENT) +object MachineAssemblyHandlerClient { + + val mc: Minecraft by lazy { + Minecraft.getMinecraft() + } + + @SubscribeEvent + fun addMachineCtrlTooltip(event: ItemTooltipEvent) { + val stack = event.itemStack + val item = stack.item + if (item is ItemBlock) { + val machine = NEWMachineAssemblyManager + .getDynamicMachine(item.block, stack.metadata) ?: return + event.toolTip.add( + I18n.format( + "tooltip.machine_assembly_tool.0", + machine.localizedName + ) + ) + event.toolTip.add( + I18n.format( + "tooltip.machine_assembly_tool.1", + ItemMachineAssemblyTool.getItemStackDisplayName(ItemStack.EMPTY) + ) + ) + } + } + + @SubscribeEvent + fun onMouseEvent(event: MouseEvent) { + if (mc.player != null && mc.player.isSneaking() && NEWBlockArrayPreviewRenderHelper.work) { + val stack: ItemStack = mc.player.heldItemMainhand + var delta = -Mouse.getEventDWheel() + if (delta % 120 == 0) { + delta /= 120 + } + if (delta != 0 && stack.item is ItemMachineAssemblyTool) { + NEWBlockArrayPreviewRenderHelper + .setLayers(NEWBlockArrayPreviewRenderHelper.getLayers() + delta) + event.isCanceled = true + } + } + } + + @SubscribeEvent + fun tick(event: TickEvent.ClientTickEvent) { + if (event.phase === TickEvent.Phase.END) { + return + } + NEWBlockArrayPreviewRenderHelper.tick() + } + + @SubscribeEvent + fun onRenderLast(event: RenderWorldLastEvent) { + if (Minecraft.getMinecraft().player == null) return + NEWBlockArrayPreviewRenderHelper.renderTranslucentBlocks() + } + + @SubscribeEvent + fun purgeDisconnect(event: FMLNetworkEvent.ClientDisconnectionFromServerEvent) { + NEWBlockArrayPreviewRenderHelper.unloadWorld() + } + + @SubscribeEvent + fun onWorldChange(unload: WorldEvent.Unload) { + if (unload.world.isRemote) { + NEWBlockArrayPreviewRenderHelper.unloadWorld() + } + } +} diff --git a/src/main/java/github/kasuminova/novaeng/client/util/ExJEI.java b/src/main/java/github/kasuminova/novaeng/client/util/ExJEI.java index 0f399635..10915331 100644 --- a/src/main/java/github/kasuminova/novaeng/client/util/ExJEI.java +++ b/src/main/java/github/kasuminova/novaeng/client/util/ExJEI.java @@ -15,15 +15,12 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; -@SideOnly(Side.CLIENT) public class ExJEI { private static final List blockList = Arrays.asList( diff --git a/src/main/java/github/kasuminova/novaeng/client/util/NEWBlockArrayPreviewRenderHelper.kt b/src/main/java/github/kasuminova/novaeng/client/util/NEWBlockArrayPreviewRenderHelper.kt new file mode 100644 index 00000000..7ec86883 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/client/util/NEWBlockArrayPreviewRenderHelper.kt @@ -0,0 +1,81 @@ +package github.kasuminova.novaeng.client.util + +import github.kasuminova.novaeng.mixin.util.BlockArrayPreviewRenderUtils +import github.kasuminova.novaeng.mixin.util.BlockArrayRenderUtils +import hellfirepvp.modularmachinery.client.util.BlockArrayPreviewRenderHelper +import hellfirepvp.modularmachinery.client.util.DynamicMachineRenderContext +import hellfirepvp.modularmachinery.common.block.BlockController +import hellfirepvp.modularmachinery.common.util.MiscUtils +import net.minecraft.client.Minecraft +import net.minecraft.util.EnumFacing +import net.minecraft.util.math.BlockPos +import net.minecraft.util.text.TextComponentTranslation + +@Suppress("CAST_NEVER_SUCCEEDS") +object NEWBlockArrayPreviewRenderHelper : BlockArrayPreviewRenderHelper() { + + val utils = this as BlockArrayPreviewRenderUtils + var renderHelperUtils: BlockArrayRenderUtils? = null + private var status: Int = 0 + var work = false + var key = 0L + + fun startPreview(currentContext: DynamicMachineRenderContext, pos: BlockPos, facing: EnumFacing?): Boolean { + if (this.startPreview(currentContext)) { + val lookState = Minecraft.getMinecraft().world.getBlockState(pos) + val rotate = facing ?: lookState.getValue(BlockController.FACING) + val moveDir = MiscUtils.rotateYCCWNorthUntil(BlockPos(utils.renderHelperOffset), rotate) + val newpos = pos.subtract(moveDir) + utils.matchArray = MiscUtils.rotateYCCWNorthUntil(utils.matchArray, rotate) + utils.attachedPosition = newpos + key = pos.toLong() + renderHelperUtils = utils.renderHelper as BlockArrayRenderUtils + utils.facing = facing + initLayers() + work = true + return true + } + return false + } + + private fun initLayers() { + val matchingArray = renderHelperUtils!!.`n$getBlocks`() + val maxSlice = matchingArray.max.y + utils.renderedLayer = maxSlice + 1 + this.status = maxSlice + 2 + } + + fun setLayers(newValue: Int) { + if (renderHelperUtils != null) { + val size = status + val mod = newValue % size + + val value = if (mod < 0) mod + size else mod + + utils.renderedLayer = value + } + } + + fun getLayers(): Int { + return utils.renderedLayer + } + + fun renderTranslucentBlocks() { + utils.`n$renderTranslucentBlocks`() + } + + fun clear() { + renderHelperUtils = null + status = 0 + work = false + key = 0 + + if (Minecraft.getMinecraft().player != null) { + Minecraft.getMinecraft().player.sendMessage( + TextComponentTranslation( + "gui.blueprint.popout.placed.dynamic_pattern.unload" + ) + ) + } + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/client/util/TitleUtils.java b/src/main/java/github/kasuminova/novaeng/client/util/TitleUtils.java index 85fb1452..5b1cc67b 100644 --- a/src/main/java/github/kasuminova/novaeng/client/util/TitleUtils.java +++ b/src/main/java/github/kasuminova/novaeng/client/util/TitleUtils.java @@ -1,8 +1,8 @@ package github.kasuminova.novaeng.client.util; +import github.kasuminova.novaeng.NovaEngCoreConfig; import github.kasuminova.novaeng.NovaEngineeringCore; import github.kasuminova.novaeng.client.hitokoto.HitokotoAPI; -import github.kasuminova.novaeng.NovaEngCoreConfig; import github.kasuminova.novaeng.mixin.NovaEngCoreEarlyMixinLoader; import org.lwjgl.opengl.Display; @@ -11,7 +11,7 @@ public class TitleUtils { /** - * TODO 喜欢我硬编码吗.jpg + * 喜欢我硬编码吗.jpg */ public static final String DEFAULT_TITLE = "Nova Engineering: World 1.18.2 by Hikari_Nova | Core Ver: " + NovaEngineeringCore.VERSION; public static final String VANILLA_TITLE = "Minecraft 1.12.2"; diff --git a/src/main/java/github/kasuminova/novaeng/common/CommonProxy.java b/src/main/java/github/kasuminova/novaeng/common/CommonProxy.java deleted file mode 100644 index 41e9fa82..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/CommonProxy.java +++ /dev/null @@ -1,264 +0,0 @@ -package github.kasuminova.novaeng.common; - -import appeng.api.AEApi; -import appeng.api.storage.ICellHandler; -import github.kasuminova.mmce.common.integration.ModIntegrationAE2; -import github.kasuminova.novaeng.NovaEngineeringCore; -import github.kasuminova.novaeng.common.adapter.RecipeAdapterExtended; -import github.kasuminova.novaeng.NovaEngCoreConfig; -import github.kasuminova.novaeng.common.container.ContainerECalculatorController; -import github.kasuminova.novaeng.common.container.ContainerEFabricatorController; -import github.kasuminova.novaeng.common.container.ContainerEFabricatorPatternBus; -import github.kasuminova.novaeng.common.container.ContainerEFabricatorPatternSearch; -import github.kasuminova.novaeng.common.container.ContainerEStorageController; -import github.kasuminova.novaeng.common.container.ContainerGeocentricDrill; -import github.kasuminova.novaeng.common.container.ContainerHyperNetTerminal; -import github.kasuminova.novaeng.common.container.ContainerModularServerAssembler; -import github.kasuminova.novaeng.common.container.ContainerSingularityCore; -import github.kasuminova.novaeng.common.enchantment.MagicBreaking; -import github.kasuminova.novaeng.common.estorage.EStorageCellHandler; -import github.kasuminova.novaeng.common.handler.ECalculatorEventHandler; -import github.kasuminova.novaeng.common.handler.EFabricatorEventHandler; -import github.kasuminova.novaeng.common.handler.EStorageEventHandler; -import github.kasuminova.novaeng.common.handler.EnchantmentHandler; -import github.kasuminova.novaeng.common.handler.FTBHandler; -import github.kasuminova.novaeng.common.handler.HyperNetEventHandler; -import github.kasuminova.novaeng.common.handler.HyperNetMachineEventHandler; -import github.kasuminova.novaeng.common.handler.IEHandler; -import github.kasuminova.novaeng.common.handler.MachineAssemblyHandler; -import github.kasuminova.novaeng.common.handler.OreHandler; -import github.kasuminova.novaeng.common.handler.WorldLoadedHandler; -import github.kasuminova.novaeng.common.hypernet.old.HyperNetTerminal; -import github.kasuminova.novaeng.common.hypernet.old.machine.AssemblyLine; -import github.kasuminova.novaeng.common.hypernet.old.recipe.HyperNetRecipeManager; -import github.kasuminova.novaeng.common.integration.IntegrationCRT; -import github.kasuminova.novaeng.common.integration.ic2.IntegrationIC2; -import github.kasuminova.novaeng.common.integration.theoneprobe.IntegrationTOP; -import github.kasuminova.novaeng.common.machine.BiogenicSimulationComputer; -import github.kasuminova.novaeng.common.machine.DreamEnergyCore; -import github.kasuminova.novaeng.common.machine.Drills.DifferentWorld; -import github.kasuminova.novaeng.common.machine.Drills.ManaOreDrill; -import github.kasuminova.novaeng.common.machine.Drills.MineralExtractor; -import github.kasuminova.novaeng.common.machine.Drills.OrichalcosDrill; -import github.kasuminova.novaeng.common.machine.Drills.SmallOreDrill; -import github.kasuminova.novaeng.common.machine.Drills.VoidMiner; -import github.kasuminova.novaeng.common.machine.GeocentricDrill; -import github.kasuminova.novaeng.common.machine.IllumPool; -import github.kasuminova.novaeng.common.machine.MMAltar; -import github.kasuminova.novaeng.common.machine.MaterialSequenceProcessing; -import github.kasuminova.novaeng.common.machine.SingularityCore; -import github.kasuminova.novaeng.common.machine.SpaceGenerator; -import github.kasuminova.novaeng.common.registry.RegistryBlocks; -import github.kasuminova.novaeng.common.registry.RegistryHyperNet; -import github.kasuminova.novaeng.common.registry.RegistryItems; -import github.kasuminova.novaeng.common.registry.RegistryMachineSpecial; -import github.kasuminova.novaeng.common.tile.TileHyperNetTerminal; -import github.kasuminova.novaeng.common.tile.TileModularServerAssembler; -import github.kasuminova.novaeng.common.tile.ecotech.ecalculator.ECalculatorController; -import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorController; -import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorPatternBus; -import github.kasuminova.novaeng.common.tile.ecotech.estorage.EStorageController; -import github.kasuminova.novaeng.common.tile.machine.GeocentricDrillController; -import github.kasuminova.novaeng.common.trait.Register; -import github.kasuminova.novaeng.common.util.MachineCoolants; -import github.kasuminova.novaeng.mixin.ae2.AccessorCellRegistry; -import hellfirepvp.modularmachinery.ModularMachinery; -import hellfirepvp.modularmachinery.common.base.Mods; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.world.World; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fml.common.Loader; -import net.minecraftforge.fml.common.network.IGuiHandler; -import net.minecraftforge.fml.common.network.NetworkRegistry; -import net.minecraftforge.fml.common.registry.ForgeRegistries; - -import javax.annotation.Nullable; -import java.util.List; - -@SuppressWarnings("MethodMayBeStatic") -public class CommonProxy implements IGuiHandler { - - public CommonProxy() { - MinecraftForge.EVENT_BUS.register(new RegistryBlocks()); - MinecraftForge.EVENT_BUS.register(new RegistryItems()); - } - - public void setColor(String od, int color) { - - } - - public boolean isClient() { - return false; - } - - public void construction() { - if (Loader.isModLoaded("ecoaeextension")) { - throw new RuntimeException("Repeatedly added MOD:ECOAEExtension"); - } - } - - public void preInit() { - NetworkRegistry.INSTANCE.registerGuiHandler(NovaEngineeringCore.MOD_ID, this); - - MinecraftForge.EVENT_BUS.register(IntegrationCRT.INSTANCE); - MinecraftForge.EVENT_BUS.register(HyperNetEventHandler.INSTANCE); - MinecraftForge.EVENT_BUS.register(EStorageEventHandler.INSTANCE); - MinecraftForge.EVENT_BUS.register(EFabricatorEventHandler.INSTANCE); - MinecraftForge.EVENT_BUS.register(ECalculatorEventHandler.INSTANCE); - MinecraftForge.EVENT_BUS.register(WorldLoadedHandler.INSTANCE); - MinecraftForge.EVENT_BUS.register(EnchantmentHandler.INSTANCE); - MinecraftForge.EVENT_BUS.register(OreHandler.INSTANCE); - MinecraftForge.EVENT_BUS.register(MachineAssemblyHandler.INSTANCE); - - if (Loader.isModLoaded("ftbquests")) - MinecraftForge.EVENT_BUS.register(FTBHandler.INSTANCE); - - if (NovaEngCoreConfig.SERVER.specialMachine) - MinecraftForge.EVENT_BUS.register(IEHandler.INSTANCE); - - if (Loader.isModLoaded("ic2")) { - IntegrationIC2.preInit(); - } - - ForgeRegistries.ENCHANTMENTS.register(MagicBreaking.MAGICBREAKING); - } - - public void init() { - RegistryHyperNet.registerHyperNetNode( - new ResourceLocation(ModularMachinery.MODID, "hypernet_terminal"), - HyperNetTerminal.class - ); - if (Loader.isModLoaded("theoneprobe")) IntegrationTOP.registerProvider(); - RecipeAdapterExtended.registerAdapter(); - AssemblyLine.registerNetNode(); - HyperNetRecipeManager.registerRecipes(); - if (NovaEngCoreConfig.SERVER.specialMachine) { - if (Mods.ASTRAL_SORCERY.isPresent() && Mods.BOTANIA.isPresent()) { - RegistryMachineSpecial.registrySpecialMachine(IllumPool.INSTANCE); - } - if (Mods.GECKOLIB.isPresent()) { - RegistryMachineSpecial.registrySpecialMachine(SingularityCore.INSTANCE); - } - if (Mods.BM2.isPresent()) { - RegistryMachineSpecial.registrySpecialMachine(MMAltar.INSTANCE); - } - RegistryMachineSpecial.registrySpecialMachine(DreamEnergyCore.INSTANCE); - RegistryMachineSpecial.registrySpecialMachine(GeocentricDrill.INSTANCE); - if (Loader.isModLoaded("deepmoblearning")) { - RegistryMachineSpecial.registrySpecialMachine(MaterialSequenceProcessing.INSTANCE); - RegistryMachineSpecial.registrySpecialMachine(BiogenicSimulationComputer.INSTANCE); - } - if (Loader.isModLoaded("avaritia")) { - RegistryMachineSpecial.registrySpecialMachine(SpaceGenerator.INSTANCE); - } - if (Loader.isModLoaded("immersiveengineering")) { - RegistryMachineSpecial.registrySpecialMachine(MineralExtractor.INSTANCE); - RegistryMachineSpecial.registrySpecialMachine(VoidMiner.INSTANCE); - RegistryMachineSpecial.registrySpecialMachine(DifferentWorld.INSTANCE); - RegistryMachineSpecial.registrySpecialMachine(ManaOreDrill.INSTANCE); - RegistryMachineSpecial.registrySpecialMachine(OrichalcosDrill.INSTANCE); - RegistryMachineSpecial.registrySpecialMachine(SmallOreDrill.INSTANCE); - } - } - if (Mods.AE2.isPresent()) { - List handlers = ((AccessorCellRegistry) (AEApi.instance().registries().cell())).getHandlers(); - handlers.add(0, EStorageCellHandler.INSTANCE); - } - Register.TRAITREGISTER.registerModifiers(); - } - - public void postInit() { - MachineCoolants.INSTANCE.init(); - HyperNetMachineEventHandler.registerHandler(); - OreHandler.registry(); - } - - public void loadComplete() { - - } - - @Nullable - @Override - public Object getServerGuiElement(final int ID, final EntityPlayer player, final World world, final int x, final int y, final int z) { - GuiType type = GuiType.values()[MathHelper.clamp(ID, 0, GuiType.values().length - 1)]; - Class required = type.requiredTileEntity; - TileEntity present = null; - if (required != null) { - TileEntity te = world.getTileEntity(new BlockPos(x, y, z)); - if (te != null && required.isAssignableFrom(te.getClass())) { - present = te; - } else { - return null; - } - } - - return switch (type) { - case HYPERNET_TERMINAL -> new ContainerHyperNetTerminal((TileHyperNetTerminal) present, player); - case MODULAR_SERVER_ASSEMBLER -> - new ContainerModularServerAssembler((TileModularServerAssembler) present, player); - case ESTORAGE_CONTROLLER -> new ContainerEStorageController((EStorageController) present, player); - case SINGULARITY_CORE -> - new ContainerSingularityCore((github.kasuminova.novaeng.common.tile.machine.SingularityCore) present, player); - case EFABRICATOR_CONTROLLER -> { - EFabricatorController efController = (EFabricatorController) present; - if (efController.getChannel() != null && ModIntegrationAE2.securityCheck(player, efController.getChannel().getProxy())) { - yield null; - } - yield new ContainerEFabricatorController(efController, player); - } - case EFABRICATOR_PATTERN_SEARCH -> { - EFabricatorController efController = (EFabricatorController) present; - if (efController.getChannel() != null && ModIntegrationAE2.securityCheck(player, efController.getChannel().getProxy())) { - yield null; - } - yield new ContainerEFabricatorPatternSearch(efController, player); - } - case EFABRICATOR_PATTERN_BUS -> { - EFabricatorPatternBus efPatternBus = (EFabricatorPatternBus) present; - EFabricatorController efController = efPatternBus.getController(); - if (efController != null && efController.getChannel() != null && ModIntegrationAE2.securityCheck(player, efController.getChannel().getProxy())) { - yield null; - } - yield new ContainerEFabricatorPatternBus(efPatternBus, player); - } - case GEOCENTRIC_DRILL_CONTROLLER -> - new ContainerGeocentricDrill((GeocentricDrillController) present, player); - case ECALCULATOR_CONTROLLER -> { - ECalculatorController ecController = (ECalculatorController) present; - if (ecController.getChannel() != null && ModIntegrationAE2.securityCheck(player, ecController.getChannel().getProxy())) { - yield null; - } - yield new ContainerECalculatorController((ECalculatorController) present, player); - } - }; - } - - @Nullable - @Override - public Object getClientGuiElement(final int ID, final EntityPlayer player, final World world, final int x, final int y, final int z) { - return null; - } - - public enum GuiType { - HYPERNET_TERMINAL(TileHyperNetTerminal.class), - MODULAR_SERVER_ASSEMBLER(TileModularServerAssembler.class), - ESTORAGE_CONTROLLER(EStorageController.class), - SINGULARITY_CORE(github.kasuminova.novaeng.common.tile.machine.SingularityCore.class), - EFABRICATOR_CONTROLLER(EFabricatorController.class), - EFABRICATOR_PATTERN_SEARCH(EFabricatorController.class), - EFABRICATOR_PATTERN_BUS(EFabricatorPatternBus.class), - GEOCENTRIC_DRILL_CONTROLLER(GeocentricDrillController.class), - ECALCULATOR_CONTROLLER(ECalculatorController.class), - ; - - public final Class requiredTileEntity; - - GuiType(@Nullable Class requiredTileEntity) { - this.requiredTileEntity = requiredTileEntity; - } - } -} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/CommonProxy.kt b/src/main/java/github/kasuminova/novaeng/common/CommonProxy.kt new file mode 100644 index 00000000..9900b95f --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/CommonProxy.kt @@ -0,0 +1,281 @@ +package github.kasuminova.novaeng.common + +import appeng.api.AEApi +import baubles.api.BaublesApi +import com.circulation.random_complement.common.util.MEHandler +import github.kasuminova.mmce.common.integration.ModIntegrationAE2 +import github.kasuminova.novaeng.NovaEngCoreConfig +import github.kasuminova.novaeng.NovaEngineeringCore +import github.kasuminova.novaeng.common.adapter.RecipeAdapterExtended +import github.kasuminova.novaeng.common.container.ContainerECalculatorController +import github.kasuminova.novaeng.common.container.ContainerEFabricatorController +import github.kasuminova.novaeng.common.container.ContainerEFabricatorPatternBus +import github.kasuminova.novaeng.common.container.ContainerEFabricatorPatternSearch +import github.kasuminova.novaeng.common.container.ContainerEStorageController +import github.kasuminova.novaeng.common.container.ContainerGeocentricDrill +import github.kasuminova.novaeng.common.container.ContainerHyperNetTerminal +import github.kasuminova.novaeng.common.container.ContainerModularServerAssembler +import github.kasuminova.novaeng.common.container.ContainerNEWCraftConfirm +import github.kasuminova.novaeng.common.container.ContainerSingularityCore +import github.kasuminova.novaeng.common.enchantment.MagicBreaking +import github.kasuminova.novaeng.common.estorage.EStorageCellHandler +import github.kasuminova.novaeng.common.handler.ECalculatorEventHandler +import github.kasuminova.novaeng.common.handler.EFabricatorEventHandler +import github.kasuminova.novaeng.common.handler.EStorageEventHandler +import github.kasuminova.novaeng.common.handler.EnchantmentHandler +import github.kasuminova.novaeng.common.handler.FTBHandler +import github.kasuminova.novaeng.common.handler.HyperNetEventHandler +import github.kasuminova.novaeng.common.handler.HyperNetMachineEventHandler +import github.kasuminova.novaeng.common.handler.IEHandler +import github.kasuminova.novaeng.common.handler.MachineAssemblyHandler +import github.kasuminova.novaeng.common.handler.OreHandler +import github.kasuminova.novaeng.common.handler.WorldLoadedHandler +import github.kasuminova.novaeng.common.hypernet.old.HyperNetTerminal +import github.kasuminova.novaeng.common.hypernet.old.machine.AssemblyLine +import github.kasuminova.novaeng.common.hypernet.old.recipe.HyperNetRecipeManager +import github.kasuminova.novaeng.common.integration.IntegrationCRT +import github.kasuminova.novaeng.common.integration.ic2.IntegrationIC2 +import github.kasuminova.novaeng.common.integration.theoneprobe.IntegrationTOP +import github.kasuminova.novaeng.common.machine.BiogenicSimulationComputer +import github.kasuminova.novaeng.common.machine.DreamEnergyCore +import github.kasuminova.novaeng.common.machine.Drills.DifferentWorld +import github.kasuminova.novaeng.common.machine.Drills.ManaOreDrill +import github.kasuminova.novaeng.common.machine.Drills.MineralExtractor +import github.kasuminova.novaeng.common.machine.Drills.OrichalcosDrill +import github.kasuminova.novaeng.common.machine.Drills.SmallOreDrill +import github.kasuminova.novaeng.common.machine.Drills.VoidMiner +import github.kasuminova.novaeng.common.machine.GeocentricDrill +import github.kasuminova.novaeng.common.machine.IllumPool +import github.kasuminova.novaeng.common.machine.MMAltar +import github.kasuminova.novaeng.common.machine.MaterialSequenceProcessing +import github.kasuminova.novaeng.common.machine.SingularityCore +import github.kasuminova.novaeng.common.machine.SpaceGenerator +import github.kasuminova.novaeng.common.registry.RegistryAssembly +import github.kasuminova.novaeng.common.registry.RegistryBlocks +import github.kasuminova.novaeng.common.registry.RegistryHyperNet +import github.kasuminova.novaeng.common.registry.RegistryItems +import github.kasuminova.novaeng.common.registry.RegistryMachineSpecial +import github.kasuminova.novaeng.common.tile.TileHyperNetTerminal +import github.kasuminova.novaeng.common.tile.TileModularServerAssembler +import github.kasuminova.novaeng.common.tile.ecotech.ecalculator.ECalculatorController +import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorController +import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorPatternBus +import github.kasuminova.novaeng.common.tile.ecotech.estorage.EStorageController +import github.kasuminova.novaeng.common.tile.machine.GeocentricDrillController +import github.kasuminova.novaeng.common.trait.Register.registerModifiers +import github.kasuminova.novaeng.common.util.MachineCoolants +import github.kasuminova.novaeng.mixin.ae2.AccessorCellRegistry +import hellfirepvp.modularmachinery.ModularMachinery +import hellfirepvp.modularmachinery.common.base.Mods +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.tileentity.TileEntity +import net.minecraft.util.ResourceLocation +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.MathHelper +import net.minecraft.world.World +import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.fml.common.Loader +import net.minecraftforge.fml.common.network.IGuiHandler +import net.minecraftforge.fml.common.network.NetworkRegistry +import net.minecraftforge.fml.common.registry.ForgeRegistries + +open class CommonProxy : IGuiHandler { + init { + MinecraftForge.EVENT_BUS.register(RegistryBlocks()) + MinecraftForge.EVENT_BUS.register(RegistryItems()) + } + + open fun setColor(od: String?, color: Int) { + } + + open val isClient: Boolean + get() = false + + open fun construction() { + if (Loader.isModLoaded("ecoaeextension")) { + throw RuntimeException("Repeatedly added MOD:ECOAEExtension") + } + } + + open fun preInit() { + NetworkRegistry.INSTANCE.registerGuiHandler(NovaEngineeringCore.MOD_ID, this) + + MinecraftForge.EVENT_BUS.register(IntegrationCRT.INSTANCE) + MinecraftForge.EVENT_BUS.register(HyperNetEventHandler.INSTANCE) + MinecraftForge.EVENT_BUS.register(EStorageEventHandler.INSTANCE) + MinecraftForge.EVENT_BUS.register(EFabricatorEventHandler.INSTANCE) + MinecraftForge.EVENT_BUS.register(ECalculatorEventHandler.INSTANCE) + MinecraftForge.EVENT_BUS.register(WorldLoadedHandler.INSTANCE) + MinecraftForge.EVENT_BUS.register(EnchantmentHandler.INSTANCE) + MinecraftForge.EVENT_BUS.register(OreHandler.INSTANCE) + MinecraftForge.EVENT_BUS.register(MachineAssemblyHandler) + + if (Loader.isModLoaded("ftbquests")) MinecraftForge.EVENT_BUS.register(FTBHandler.INSTANCE) + + if (NovaEngCoreConfig.SERVER.specialMachine) MinecraftForge.EVENT_BUS.register(IEHandler.INSTANCE) + + if (Loader.isModLoaded("ic2")) { + IntegrationIC2.preInit() + } + + ForgeRegistries.ENCHANTMENTS.register(MagicBreaking.MAGICBREAKING) + } + + open fun init() { + RegistryHyperNet.registerHyperNetNode( + ResourceLocation(ModularMachinery.MODID, "hypernet_terminal"), + HyperNetTerminal::class.java + ) + if (Loader.isModLoaded("theoneprobe")) IntegrationTOP.registerProvider() + RecipeAdapterExtended.registerAdapter() + AssemblyLine.registerNetNode() + HyperNetRecipeManager.registerRecipes() + if (NovaEngCoreConfig.SERVER.specialMachine) { + if (Mods.ASTRAL_SORCERY.isPresent && Mods.BOTANIA.isPresent) { + RegistryMachineSpecial.registrySpecialMachine(IllumPool.INSTANCE) + } + if (Mods.GECKOLIB.isPresent) { + RegistryMachineSpecial.registrySpecialMachine(SingularityCore.INSTANCE) + } + if (Mods.BM2.isPresent) { + RegistryMachineSpecial.registrySpecialMachine(MMAltar.INSTANCE) + } + RegistryMachineSpecial.registrySpecialMachine(DreamEnergyCore.INSTANCE) + RegistryMachineSpecial.registrySpecialMachine(GeocentricDrill.INSTANCE) + if (Loader.isModLoaded("deepmoblearning")) { + RegistryMachineSpecial.registrySpecialMachine(MaterialSequenceProcessing.INSTANCE) + RegistryMachineSpecial.registrySpecialMachine(BiogenicSimulationComputer.INSTANCE) + } + if (Loader.isModLoaded("avaritia")) { + RegistryMachineSpecial.registrySpecialMachine(SpaceGenerator.INSTANCE) + } + if (Loader.isModLoaded("immersiveengineering")) { + RegistryMachineSpecial.registrySpecialMachine(MineralExtractor.INSTANCE) + RegistryMachineSpecial.registrySpecialMachine(VoidMiner.INSTANCE) + RegistryMachineSpecial.registrySpecialMachine(DifferentWorld.INSTANCE) + RegistryMachineSpecial.registrySpecialMachine(ManaOreDrill.INSTANCE) + RegistryMachineSpecial.registrySpecialMachine(OrichalcosDrill.INSTANCE) + RegistryMachineSpecial.registrySpecialMachine(SmallOreDrill.INSTANCE) + } + } + if (Mods.AE2.isPresent) { + val handlers = ((AEApi.instance().registries().cell()) as AccessorCellRegistry).getHandlers() + handlers.add(0, EStorageCellHandler.INSTANCE) + } + registerModifiers() + } + + open fun postInit() { + RegistryAssembly.regAll() + MachineCoolants.INSTANCE.init() + HyperNetMachineEventHandler.registerHandler() + OreHandler.registry() + } + + open fun loadComplete() { + + } + + override fun getServerGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): Any? { + val type = GuiType.entries[MathHelper.clamp(id, 0, GuiType.entries.size - 1)] + val required = type.requiredTileEntity + var present: TileEntity? = null + if (required != null) { + val te = world.getTileEntity(BlockPos(x, y, z)) + if (te != null && required.isAssignableFrom(te.javaClass)) { + present = te + } else { + return null + } + } + + return when (type) { + GuiType.HYPERNET_TERMINAL -> ContainerHyperNetTerminal(present as TileHyperNetTerminal?, player) + GuiType.MODULAR_SERVER_ASSEMBLER -> ContainerModularServerAssembler( + (present as TileModularServerAssembler?)!!, + player + ) + + GuiType.ESTORAGE_CONTROLLER -> ContainerEStorageController(present as EStorageController?, player) + GuiType.SINGULARITY_CORE -> ContainerSingularityCore( + present as github.kasuminova.novaeng.common.tile.machine.SingularityCore?, + player + ) + + GuiType.EFABRICATOR_CONTROLLER -> { + val efController = present as? EFabricatorController + return if (efController != null && efController.channel != null && ModIntegrationAE2.securityCheck( + player, efController.channel!!.proxy + ) + ) { + null + } else ContainerEFabricatorController(efController, player) + } + + GuiType.EFABRICATOR_PATTERN_SEARCH -> { + val efController = present as? EFabricatorController + return if (efController != null && efController.channel != null && ModIntegrationAE2.securityCheck( + player, efController.channel!!.proxy + ) + ) { + null + } else ContainerEFabricatorPatternSearch(efController, player) + } + + GuiType.EFABRICATOR_PATTERN_BUS -> { + val efPatternBus = present as? EFabricatorPatternBus + val efController = efPatternBus?.controller + return if (efController != null && efController.channel != null && ModIntegrationAE2.securityCheck( + player, efController.channel!!.proxy + ) + ) { + null + } else ContainerEFabricatorPatternBus(efPatternBus, player) + } + + GuiType.GEOCENTRIC_DRILL_CONTROLLER -> ContainerGeocentricDrill( + present as GeocentricDrillController?, + player + ) + + GuiType.ECALCULATOR_CONTROLLER -> { + val ecController = present as ECalculatorController? + return if (ecController != null && ecController.channel != null && ModIntegrationAE2.securityCheck( + player, ecController.channel.getProxy() + ) + ) { + null + } else ContainerECalculatorController(present, player) + } + + GuiType.AUTO_CRAFTGUI -> { + val stack = if (y == 1) BaublesApi.getBaublesHandler(player).getStackInSlot(x) + else player.inventory.getStackInSlot(x) + + MEHandler.getTerminalGuiObject(stack, player, x, y)?.let { + return ContainerNEWCraftConfirm(player.inventory, it) + } + return null + } + GuiType.MACHINE_ASSEMBLY_TOOL -> null + } + } + + override fun getClientGuiElement(id: Int, player: EntityPlayer?, world: World?, x: Int, y: Int, z: Int): Any? { + return null + } + + enum class GuiType(@JvmField val requiredTileEntity: Class?) { + HYPERNET_TERMINAL(TileHyperNetTerminal::class.java), + MODULAR_SERVER_ASSEMBLER(TileModularServerAssembler::class.java), + ESTORAGE_CONTROLLER(EStorageController::class.java), + SINGULARITY_CORE(github.kasuminova.novaeng.common.tile.machine.SingularityCore::class.java), + EFABRICATOR_CONTROLLER(EFabricatorController::class.java), + EFABRICATOR_PATTERN_SEARCH(EFabricatorController::class.java), + EFABRICATOR_PATTERN_BUS(EFabricatorPatternBus::class.java), + GEOCENTRIC_DRILL_CONTROLLER(GeocentricDrillController::class.java), + ECALCULATOR_CONTROLLER(ECalculatorController::class.java), + AUTO_CRAFTGUI(null), + MACHINE_ASSEMBLY_TOOL(null) + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/block/BlockHyperNetTerminal.java b/src/main/java/github/kasuminova/novaeng/common/block/BlockHyperNetTerminal.java index 95260deb..80e002be 100644 --- a/src/main/java/github/kasuminova/novaeng/common/block/BlockHyperNetTerminal.java +++ b/src/main/java/github/kasuminova/novaeng/common/block/BlockHyperNetTerminal.java @@ -117,7 +117,7 @@ public void breakBlock(World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockStat spawnAsEntity(worldIn, pos, stackCtrl); } - // TODO MM warn. + //MM warn. super.breakBlock(worldIn, pos, state); } diff --git a/src/main/java/github/kasuminova/novaeng/common/container/ContainerEFabricatorPatternSearch.java b/src/main/java/github/kasuminova/novaeng/common/container/ContainerEFabricatorPatternSearch.java deleted file mode 100644 index 7c06e469..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/container/ContainerEFabricatorPatternSearch.java +++ /dev/null @@ -1,26 +0,0 @@ -package github.kasuminova.novaeng.common.container; - -import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorController; -import hellfirepvp.modularmachinery.common.container.ContainerBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.Slot; - -public class ContainerEFabricatorPatternSearch extends ContainerBase { - - public ContainerEFabricatorPatternSearch(final EFabricatorController owner, final EntityPlayer opening) { - super(owner, opening); - } - - @Override - protected void addPlayerSlots(EntityPlayer opening) { - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 9; j++) { - addSlotToContainer(new Slot(opening.inventory, j + i * 9 + 9, 18 + j * 18, (119 + 11) + i * 18)); - } - } - for (int i = 0; i < 9; i++) { - addSlotToContainer(new Slot(opening.inventory, i, 18 + i * 18, 177 + 11)); - } - } - -} diff --git a/src/main/java/github/kasuminova/novaeng/common/container/ContainerEFabricatorPatternSearch.kt b/src/main/java/github/kasuminova/novaeng/common/container/ContainerEFabricatorPatternSearch.kt new file mode 100644 index 00000000..7437790e --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/container/ContainerEFabricatorPatternSearch.kt @@ -0,0 +1,20 @@ +package github.kasuminova.novaeng.common.container + +import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorController +import hellfirepvp.modularmachinery.common.container.ContainerBase +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.inventory.Slot + +open class ContainerEFabricatorPatternSearch(owner: EFabricatorController?, opening: EntityPlayer?) : + ContainerBase(owner, opening) { + override fun addPlayerSlots(opening: EntityPlayer) { + for (i in 0..2) { + for (j in 0..8) { + addSlotToContainer(Slot(opening.inventory, j + i * 9 + 9, 18 + j * 18, (119 + 11) + i * 18)) + } + } + for (i in 0..8) { + addSlotToContainer(Slot(opening.inventory, i, 18 + i * 18, 177 + 11)) + } + } +} diff --git a/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerAssembler.java b/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerAssembler.java deleted file mode 100644 index d6385aad..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerAssembler.java +++ /dev/null @@ -1,124 +0,0 @@ -package github.kasuminova.novaeng.common.container; - -import github.kasuminova.novaeng.common.container.slot.AssemblySlotManager; -import github.kasuminova.novaeng.common.container.slot.SlotModularServer; -import github.kasuminova.novaeng.common.hypernet.computer.ModularServer; -import github.kasuminova.novaeng.common.tile.TileModularServerAssembler; -import hellfirepvp.modularmachinery.common.container.ContainerBase; -import lombok.Getter; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.Slot; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; - -public class ContainerModularServerAssembler extends ContainerBase { - protected final EntityPlayer opening; - @Getter - protected final SlotModularServer slotModularServer; - - @Getter - protected AssemblySlotManager slotManager; - - public ContainerModularServerAssembler(final TileModularServerAssembler owner, final EntityPlayer opening) { - super(owner, opening); - this.opening = opening; - - ModularServer server = owner.getServer(); - this.slotManager = server == null ? null : server.getSlotManager(); - if (this.slotManager != null) { - this.slotManager.addAllSlotToContainer(this); - } - - slotModularServer = new SlotModularServer(owner.getServerInventory().asGUIAccess(), 0, 302, 126); - this.addSlotToContainer(slotModularServer); - this.owner.addContainer(this); - } - - @Override - public void onContainerClosed(@Nonnull final EntityPlayer playerIn) { - super.onContainerClosed(playerIn); - this.owner.removeContainer(this); - } - - public void reInitSlots() { - this.inventorySlots.clear(); - this.inventoryItemStacks.clear(); - this.addPlayerSlots(opening); - - ModularServer server = owner.getServer(); - this.slotManager = server == null ? null : server.getSlotManager(); - if (this.slotManager != null) { - this.slotManager.addAllSlotToContainer(this); - } - - this.addSlotToContainer(slotModularServer); - } - - @Nonnull - @Override - public Slot addSlotToContainer(@Nonnull final Slot slotIn) { - return super.addSlotToContainer(slotIn); - } - - @Nonnull - @Override - public ItemStack transferStackInSlot(@Nonnull final EntityPlayer playerIn, final int index) { - ItemStack itemstack = ItemStack.EMPTY; - Slot slot = this.inventorySlots.get(index); - - if (slot != null && slot.getHasStack()) { - ItemStack stackInSlot = slot.getStack(); - itemstack = stackInSlot.copy(); - - if (index < 36) { -// if (!itemstack1.isEmpty() && itemstack1.getItem() instanceof ItemBlueprint) { -// Slot sb = this.inventorySlots.get(this.slotBlueprint.slotNumber); -// if (!sb.getHasStack()) { -// if (!this.mergeItemStack(itemstack1, sb.slotNumber, sb.slotNumber + 1, false)) { -// return ItemStack.EMPTY; -// } -// } -// } - } - - if (index < 27) { - if (!this.mergeItemStack(stackInSlot, 27, 36, false)) { - return ItemStack.EMPTY; - } - } else if (index < 36) { - if (!this.mergeItemStack(stackInSlot, 0, 27, false)) { - return ItemStack.EMPTY; - } - } else if (!this.mergeItemStack(stackInSlot, 0, 36, false)) { - return ItemStack.EMPTY; - } - - if (stackInSlot.getCount() == 0) { - slot.putStack(ItemStack.EMPTY); - } else { - slot.onSlotChanged(); - } - - if (stackInSlot.getCount() == itemstack.getCount()) { - return ItemStack.EMPTY; - } - - slot.onTake(playerIn, stackInSlot); - } - - return itemstack; - } - - @Override - protected void addPlayerSlots(EntityPlayer opening) { - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 9; j++) { - addSlotToContainer(new Slot(opening.inventory, j + i * 9 + 9, 133 + j * 18, 124 + i * 18)); - } - } - for (int i = 0; i < 9; i++) { - addSlotToContainer(new Slot(opening.inventory, i, 133 + i * 18, 182)); - } - } -} diff --git a/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerAssembler.kt b/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerAssembler.kt new file mode 100644 index 00000000..152925dc --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerAssembler.kt @@ -0,0 +1,115 @@ +package github.kasuminova.novaeng.common.container + +import github.kasuminova.novaeng.common.container.slot.AssemblySlotManager +import github.kasuminova.novaeng.common.container.slot.SlotModularServer +import github.kasuminova.novaeng.common.tile.TileModularServerAssembler +import hellfirepvp.modularmachinery.common.container.ContainerBase +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.inventory.Slot +import net.minecraft.item.ItemStack +import javax.annotation.Nonnull + +open class ContainerModularServerAssembler(owner: TileModularServerAssembler, protected val opening: EntityPlayer) : + ContainerBase( + owner, + opening + ) { + protected val slotModularServer: SlotModularServer + + var slotManager: AssemblySlotManager? + + init { + val server = owner.getServer() + this.slotManager = server?.getSlotManager() + if (this.slotManager != null) { + this.slotManager!!.addAllSlotToContainer(this) + } + + slotModularServer = SlotModularServer(owner.getServerInventory().asGUIAccess(), 0, 302, 126) + this.addSlotToContainer(slotModularServer) + this.owner!!.addContainer(this) + } + + override fun onContainerClosed(@Nonnull playerIn: EntityPlayer) { + super.onContainerClosed(playerIn) + this.owner!!.removeContainer(this) + } + + fun reInitSlots() { + this.inventorySlots.clear() + this.inventoryItemStacks.clear() + this.addPlayerSlots(opening) + + val server = owner!!.getServer() + this.slotManager = server?.getSlotManager() + if (this.slotManager != null) { + this.slotManager!!.addAllSlotToContainer(this) + } + + this.addSlotToContainer(slotModularServer) + } + + @Nonnull + public override fun addSlotToContainer(@Nonnull slotIn: Slot): Slot { + return super.addSlotToContainer(slotIn) + } + + @Nonnull + override fun transferStackInSlot(@Nonnull playerIn: EntityPlayer, index: Int): ItemStack { + var itemstack = ItemStack.EMPTY + val slot = this.inventorySlots[index] + + if (slot != null && slot.hasStack) { + val stackInSlot = slot.stack + itemstack = stackInSlot.copy() + + if (index < 36) { +// if (!itemstack1.isEmpty() && itemstack1.getItem() instanceof ItemBlueprint) { +// Slot sb = this.inventorySlots.get(this.slotBlueprint.slotNumber); +// if (!sb.getHasStack()) { +// if (!this.mergeItemStack(itemstack1, sb.slotNumber, sb.slotNumber + 1, false)) { +// return ItemStack.EMPTY; +// } +// } +// } + } + + if (index < 27) { + if (!this.mergeItemStack(stackInSlot, 27, 36, false)) { + return ItemStack.EMPTY + } + } else if (index < 36) { + if (!this.mergeItemStack(stackInSlot, 0, 27, false)) { + return ItemStack.EMPTY + } + } else if (!this.mergeItemStack(stackInSlot, 0, 36, false)) { + return ItemStack.EMPTY + } + + if (stackInSlot.count == 0) { + slot.putStack(ItemStack.EMPTY) + } else { + slot.onSlotChanged() + } + + if (stackInSlot.count == itemstack.count) { + return ItemStack.EMPTY + } + + slot.onTake(playerIn, stackInSlot) + } + + return itemstack + } + + override fun addPlayerSlots(opening: EntityPlayer) { + for (i in 0..2) { + for (j in 0..8) { + addSlotToContainer(Slot(opening.inventory, j + i * 9 + 9, 133 + j * 18, 124 + i * 18)) + } + } + for (i in 0..8) { + addSlotToContainer(Slot(opening.inventory, i, 133 + i * 18, 182)) + } + } +} diff --git a/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerFrame.java b/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerFrame.java deleted file mode 100644 index 9332cee3..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerFrame.java +++ /dev/null @@ -1,11 +0,0 @@ -package github.kasuminova.novaeng.common.container; - -import github.kasuminova.novaeng.common.tile.TileModularServerFrame; -import hellfirepvp.modularmachinery.common.container.ContainerBase; -import net.minecraft.entity.player.EntityPlayer; - -public class ContainerModularServerFrame extends ContainerBase { - public ContainerModularServerFrame(final TileModularServerFrame owner, final EntityPlayer opening) { - super(owner, opening); - } -} diff --git a/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerFrame.kt b/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerFrame.kt new file mode 100644 index 00000000..65e9e88a --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/container/ContainerModularServerFrame.kt @@ -0,0 +1,8 @@ +package github.kasuminova.novaeng.common.container + +import github.kasuminova.novaeng.common.tile.TileModularServerFrame +import hellfirepvp.modularmachinery.common.container.ContainerBase +import net.minecraft.entity.player.EntityPlayer + +class ContainerModularServerFrame(owner: TileModularServerFrame?, opening: EntityPlayer?) : + ContainerBase(owner, opening) diff --git a/src/main/java/github/kasuminova/novaeng/common/container/ContainerNEWCraftConfirm.kt b/src/main/java/github/kasuminova/novaeng/common/container/ContainerNEWCraftConfirm.kt new file mode 100644 index 00000000..1d995ab1 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/container/ContainerNEWCraftConfirm.kt @@ -0,0 +1,47 @@ +package github.kasuminova.novaeng.common.container + +import appeng.api.networking.crafting.ICraftingGrid +import appeng.api.networking.security.IActionHost +import appeng.container.implementations.ContainerCraftConfirm +import appeng.helpers.WirelessTerminalGuiObject +import appeng.me.helpers.PlayerSource +import github.kasuminova.novaeng.common.util.AutoCraftingQueue +import github.kasuminova.novaeng.mixin.ae2.AccessorContainerCraftConfirm +import github.kasuminova.novaeng.mixin.ae2.AccessorCraftingCPURecord +import net.minecraft.entity.player.EntityPlayerMP +import net.minecraft.entity.player.InventoryPlayer + +class ContainerNEWCraftConfirm(ip: InventoryPlayer, te: WirelessTerminalGuiObject) : ContainerCraftConfirm(ip, te) { + + override fun startJob() { + @Suppress("USELESS_IS_CHECK") + if (this is AccessorContainerCraftConfirm) { + val h = this.target as? IActionHost + h?.actionableNode?.grid?.let { grid -> + if (this.`n$getResult`() != null && !this.isSimulation) { + val cc = grid.getCache(ICraftingGrid::class.java) + cc.submitJob( + this.`n$getResult`(), + null, + if (this.getSelectedCpu() == -1) null + else { + val c = this.`n$getCpus`()[this.getSelectedCpu()] + if (c is AccessorCraftingCPURecord) { + c.`n$getCpu`() + } else null + }, + true, + PlayerSource(this.playerInv.player, h) + ) + } + } + val player = playerInv.player as EntityPlayerMP + AutoCraftingQueue.getQueue(player)?.let { + if (!it.executionQueue(player)) { + player.closeContainer() + } + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/container/ContainerSingularityCore.java b/src/main/java/github/kasuminova/novaeng/common/container/ContainerSingularityCore.java deleted file mode 100644 index b6c097cb..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/container/ContainerSingularityCore.java +++ /dev/null @@ -1,32 +0,0 @@ -package github.kasuminova.novaeng.common.container; - -import github.kasuminova.novaeng.common.tile.machine.SingularityCore; -import hellfirepvp.modularmachinery.common.container.ContainerBase; -import lombok.Getter; -import lombok.Setter; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.Slot; - -public class ContainerSingularityCore extends ContainerBase { - - @Setter - @Getter - protected int tickExisted = 0; - - public ContainerSingularityCore(final SingularityCore owner, final EntityPlayer opening) { - super(owner, opening); - } - - @Override - protected void addPlayerSlots(EntityPlayer opening) { - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 9; j++) { - addSlotToContainer(new Slot(opening.inventory, j + i * 9 + 9, 119 + j * 18, 184 + i * 18)); - } - } - for (int i = 0; i < 9; i++) { - addSlotToContainer(new Slot(opening.inventory, i, 119 + i * 18, 242)); - } - } - -} diff --git a/src/main/java/github/kasuminova/novaeng/common/container/ContainerSingularityCore.kt b/src/main/java/github/kasuminova/novaeng/common/container/ContainerSingularityCore.kt new file mode 100644 index 00000000..a34f38cb --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/container/ContainerSingularityCore.kt @@ -0,0 +1,23 @@ +package github.kasuminova.novaeng.common.container + +import github.kasuminova.novaeng.common.tile.machine.SingularityCore +import hellfirepvp.modularmachinery.common.container.ContainerBase +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.inventory.Slot + +open class ContainerSingularityCore(owner: SingularityCore?, opening: EntityPlayer?) : + ContainerBase(owner, opening) { + + protected var tickExisted: Int = 0 + + override fun addPlayerSlots(opening: EntityPlayer) { + for (i in 0..2) { + for (j in 0..8) { + addSlotToContainer(Slot(opening.inventory, j + i * 9 + 9, 119 + j * 18, 184 + i * 18)) + } + } + for (i in 0..8) { + addSlotToContainer(Slot(opening.inventory, i, 119 + i * 18, 242)) + } + } +} diff --git a/src/main/java/github/kasuminova/novaeng/common/container/slot/AssemblySlotManager.java b/src/main/java/github/kasuminova/novaeng/common/container/slot/AssemblySlotManager.java deleted file mode 100644 index ea6df57d..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/container/slot/AssemblySlotManager.java +++ /dev/null @@ -1,144 +0,0 @@ -package github.kasuminova.novaeng.common.container.slot; - -import github.kasuminova.novaeng.common.container.ContainerModularServerAssembler; -import github.kasuminova.novaeng.common.hypernet.computer.ModularServer; -import github.kasuminova.novaeng.common.hypernet.computer.assembly.AssemblyInvCPUConst; -import github.kasuminova.novaeng.common.hypernet.computer.assembly.AssemblyInvCalculateCardConst; -import github.kasuminova.novaeng.common.hypernet.computer.assembly.AssemblyInvExtensionConst; -import github.kasuminova.novaeng.common.hypernet.computer.assembly.AssemblyInvPowerConst; -import github.kasuminova.novaeng.common.util.TileItemHandler; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import javax.annotation.Nonnull; -import java.util.HashMap; -import java.util.Map; - -public class AssemblySlotManager { - private final ModularServer modularServer; - - private final Map> inventorySlots = new HashMap<>(); - - public AssemblySlotManager(final ModularServer modularServer) { - this.modularServer = modularServer; - } - - public void initSlots() { - addCPUSlots(); - addCalculateCardSlots(); - addExtensionCardSlots(); - addPowerSlots(); - } - - protected void addCPUSlots() { - TileItemHandler invCPU = modularServer.getInvByName("cpu"); - - SlotCPUExtItemHandler ext_2 = addSlot(new SlotCPUExtItemHandler(AssemblyInvCPUConst.CPU_EXTENSION_SLOT_ID, invCPU)); - - // Default CPU Slots - for (int i = 0; i < 2; i++) { - addSlot(new SlotCPUItemHandler(i, i, invCPU)) - .softDependsOn(addSlot(new SlotCPUHeatRadiatorItemHandler(i, AssemblyInvCPUConst.CPU_HEAT_RADIATOR_SLOT_ID_START + i, invCPU))); - } - // Extension CPU Slots - for (int i = 0; i < 2; i++) { - addSlot(new SlotCPUItemHandler(2 + i, 2 + i, invCPU)) - .softDependsOn(addSlot(new SlotCPUHeatRadiatorItemHandler(2 + i, AssemblyInvCPUConst.CPU_HEAT_RADIATOR_SLOT_ID_START + 2 + i, invCPU)) - .dependsOn(ext_2)) - .dependsOn(ext_2); - } - - // Default RAM Slots - for (int i = 0; i < 8; i++) { - addSlot(new SlotRAMItemHandler(i, AssemblyInvCPUConst.RAM_SLOT_ID_START + i, invCPU)) - .softDependsOn(addSlot(new SlotRAMHeatRadiatorItemHandler(i, AssemblyInvCPUConst.RAM_HEAT_RADIATOR_SLOT_ID_START + i, invCPU))); - } - // Extension RAM Slots - for (int i = 0; i < 8; i++) { - addSlot(new SlotRAMItemHandler(8 + i, AssemblyInvCPUConst.RAM_SLOT_ID_START + 8 + i, invCPU)) - .softDependsOn(addSlot(new SlotRAMHeatRadiatorItemHandler(8 + i, AssemblyInvCPUConst.RAM_HEAT_RADIATOR_SLOT_ID_START + 8 + i, invCPU)) - .dependsOn(ext_2)) - .dependsOn(ext_2); - } - } - - protected void addCalculateCardSlots() { - TileItemHandler invCalculateCard = modularServer.getInvByName("calculate_card"); - - for (int extSlotID = 0; extSlotID < AssemblyInvCalculateCardConst.LINES; extSlotID++) { - SlotCalculateCardExtItemHandler calculateCardExt = addSlot(new SlotCalculateCardExtItemHandler( - extSlotID, AssemblyInvCalculateCardConst.EXT_SLOT_ID_START + extSlotID, invCalculateCard - )); - - for (int slotID = 0; slotID < AssemblyInvCalculateCardConst.LINE_SLOTS; slotID++) { - int id = (extSlotID * AssemblyInvCalculateCardConst.LINE_SLOTS) + slotID; - addSlot(new SlotCalculateCardItemHandler(id, id, invCalculateCard) - .softDependsOn(addSlot(new SlotCalculateCardHeatRadiatorItemHandler(id, AssemblyInvCalculateCardConst.HEAT_RADIATOR_SLOT_ID_START + id, invCalculateCard)) - .dependsOn(calculateCardExt))) - .dependsOn(calculateCardExt); - } - } - } - - protected void addExtensionCardSlots() { - TileItemHandler invExtensionCard = modularServer.getInvByName("extension"); - - for (int extSlotID = 0; extSlotID < AssemblyInvExtensionConst.LINES; extSlotID++) { - SlotExtensionCardExtItemHandler calculateCardExt = addSlot(new SlotExtensionCardExtItemHandler( - extSlotID, AssemblyInvExtensionConst.EXT_SLOT_ID_START + extSlotID, invExtensionCard - )); - - for (int slotID = 0; slotID < AssemblyInvExtensionConst.LINE_SLOTS; slotID++) { - int id = (extSlotID * AssemblyInvExtensionConst.LINE_SLOTS) + slotID; - addSlot(new SlotExtensionCardItemHandler(id, id, invExtensionCard) - .softDependsOn(addSlot(new SlotExtensionCardHeatRadiatorItemHandler(id, AssemblyInvExtensionConst.HEAT_RADIATOR_SLOT_ID_START + id, invExtensionCard)) - .dependsOn(calculateCardExt))) - .dependsOn(calculateCardExt); - } - } - } - - protected void addPowerSlots() { - TileItemHandler invPower = modularServer.getInvByName("power"); - - for (int slotID = 0; slotID < 4; slotID++) { - addSlot(new SlotPSUItemHandler(slotID, slotID, invPower)); - } - for (int slotID = 0; slotID < 4; slotID++) { - addSlot(new SlotCapacitorItemHandler(slotID, AssemblyInvPowerConst.CAPACITOR_SLOT_ID_START + slotID, invPower)); - } - } - - public SLOT addSlot(@Nonnull final SLOT slot) { - TileItemHandler inv = slot.getItemHandler(); - int slotID = slot.getSlotIndex(); - inventorySlots.computeIfAbsent(inv.getInvName(), v -> new Int2ObjectOpenHashMap<>()).put(slotID, slot); - return slot; - } - - public void addSlot(@Nonnull final SlotConditionItemHandler slot, @Nonnull final TileItemHandler tileItemHandler, @Nonnull final String invName, final int slotId) { - if (tileItemHandler.isSlotAvailable(slotId)) { - inventorySlots.computeIfAbsent(invName, v -> new Int2ObjectOpenHashMap<>()).put(slotId, slot); - } - } - - public void addAllSlotToContainer(final ContainerModularServerAssembler container) { - for (final Int2ObjectMap invSlots : inventorySlots.values()) { - for (final SlotConditionItemHandler slot : invSlots.values()) { - container.addSlotToContainer(slot); - } - } - } - - public SlotConditionItemHandler getSlot(@Nonnull final String invName, final int slotId) { - Int2ObjectMap invSlots = inventorySlots.get(invName); - if (invSlots != null) { - SlotConditionItemHandler slot = invSlots.get(slotId); - if (slot.getItemHandler().isSlotAvailable(slotId)) { - return slot; - } - } - return null; - } - -} diff --git a/src/main/java/github/kasuminova/novaeng/common/container/slot/AssemblySlotManager.kt b/src/main/java/github/kasuminova/novaeng/common/container/slot/AssemblySlotManager.kt new file mode 100644 index 00000000..437bc264 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/container/slot/AssemblySlotManager.kt @@ -0,0 +1,211 @@ +package github.kasuminova.novaeng.common.container.slot + +import github.kasuminova.novaeng.common.container.ContainerModularServerAssembler +import github.kasuminova.novaeng.common.hypernet.computer.ModularServer +import github.kasuminova.novaeng.common.hypernet.computer.assembly.AssemblyInvCPUConst +import github.kasuminova.novaeng.common.hypernet.computer.assembly.AssemblyInvCalculateCardConst +import github.kasuminova.novaeng.common.hypernet.computer.assembly.AssemblyInvExtensionConst +import github.kasuminova.novaeng.common.hypernet.computer.assembly.AssemblyInvPowerConst +import github.kasuminova.novaeng.common.util.TileItemHandler +import it.unimi.dsi.fastutil.ints.Int2ObjectMap +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap +import javax.annotation.Nonnull + +open class AssemblySlotManager(private val modularServer: ModularServer) { + private val inventorySlots: MutableMap> = + HashMap() + + fun initSlots() { + addCPUSlots() + addCalculateCardSlots() + addExtensionCardSlots() + addPowerSlots() + } + + protected fun addCPUSlots() { + val invCPU = modularServer.getInvByName("cpu") + + val ext2 = + addSlot(SlotCPUExtItemHandler(AssemblyInvCPUConst.CPU_EXTENSION_SLOT_ID, invCPU)) + + // Default CPU Slots + for (i in 0..1) { + addSlot(SlotCPUItemHandler(i, i, invCPU))!! + .softDependsOn( + addSlot( + SlotCPUHeatRadiatorItemHandler( + i, + AssemblyInvCPUConst.CPU_HEAT_RADIATOR_SLOT_ID_START + i, + invCPU + ) + ) + ) + } + // Extension CPU Slots + for (i in 0..1) { + addSlot(SlotCPUItemHandler(2 + i, 2 + i, invCPU))!! + .softDependsOn( + addSlot( + SlotCPUHeatRadiatorItemHandler( + 2 + i, + AssemblyInvCPUConst.CPU_HEAT_RADIATOR_SLOT_ID_START + 2 + i, + invCPU + ) + )!! + .dependsOn(ext2) + ) + .dependsOn(ext2) + } + + // Default RAM Slots + for (i in 0..7) { + addSlot(SlotRAMItemHandler(i, AssemblyInvCPUConst.RAM_SLOT_ID_START + i, invCPU))!! + .softDependsOn( + addSlot( + SlotRAMHeatRadiatorItemHandler( + i, + AssemblyInvCPUConst.RAM_HEAT_RADIATOR_SLOT_ID_START + i, + invCPU + ) + ) + ) + } + // Extension RAM Slots + for (i in 0..7) { + addSlot( + SlotRAMItemHandler( + 8 + i, + AssemblyInvCPUConst.RAM_SLOT_ID_START + 8 + i, + invCPU + ) + )!! + .softDependsOn( + addSlot( + SlotRAMHeatRadiatorItemHandler( + 8 + i, + AssemblyInvCPUConst.RAM_HEAT_RADIATOR_SLOT_ID_START + 8 + i, + invCPU + ) + )!! + .dependsOn(ext2) + ) + .dependsOn(ext2) + } + } + + protected fun addCalculateCardSlots() { + val invCalculateCard = modularServer.getInvByName("calculate_card") + + for (extSlotID in 0..( + SlotCalculateCardExtItemHandler( + extSlotID, AssemblyInvCalculateCardConst.EXT_SLOT_ID_START + extSlotID, invCalculateCard + ) + ) + + for (slotID in 0..( + SlotCalculateCardItemHandler(id, id, invCalculateCard) + .softDependsOn( + addSlot( + SlotCalculateCardHeatRadiatorItemHandler( + id, + AssemblyInvCalculateCardConst.HEAT_RADIATOR_SLOT_ID_START + id, + invCalculateCard + ) + )!! + .dependsOn(calculateCardExt) + ) + )!! + .dependsOn(calculateCardExt) + } + } + } + + protected fun addExtensionCardSlots() { + val invExtensionCard = modularServer.getInvByName("extension") + + for (extSlotID in 0..( + SlotExtensionCardExtItemHandler( + extSlotID, AssemblyInvExtensionConst.EXT_SLOT_ID_START + extSlotID, invExtensionCard + ) + ) + + for (slotID in 0..( + SlotExtensionCardItemHandler(id, id, invExtensionCard) + .softDependsOn( + addSlot( + SlotExtensionCardHeatRadiatorItemHandler( + id, + AssemblyInvExtensionConst.HEAT_RADIATOR_SLOT_ID_START + id, + invExtensionCard + ) + )!! + .dependsOn(calculateCardExt) + ) + )!! + .dependsOn(calculateCardExt) + } + } + } + + protected fun addPowerSlots() { + val invPower = modularServer.getInvByName("power") + + for (slotID in 0..3) { + addSlot(SlotPSUItemHandler(slotID, slotID, invPower)) + } + for (slotID in 0..3) { + addSlot( + SlotCapacitorItemHandler( + slotID, + AssemblyInvPowerConst.CAPACITOR_SLOT_ID_START + slotID, + invPower + ) + ) + } + } + + fun addSlot(@Nonnull slot: SLOT?): SLOT { + val inv = slot!!.itemHandler + val slotID = slot.slotIndex + inventorySlots.computeIfAbsent(inv.invName) { v: String? -> Int2ObjectOpenHashMap() } + .put(slotID, slot) + return slot + } + + fun addSlot( + @Nonnull slot: SlotConditionItemHandler, + @Nonnull tileItemHandler: TileItemHandler, + @Nonnull invName: String, + slotId: Int + ) { + if (tileItemHandler.isSlotAvailable(slotId)) { + inventorySlots.computeIfAbsent(invName) { v: String? -> Int2ObjectOpenHashMap() } + .put(slotId, slot) + } + } + + fun addAllSlotToContainer(container: ContainerModularServerAssembler) { + for (invSlots in inventorySlots.values) { + for (slot in invSlots.values) { + container.addSlotToContainer(slot) + } + } + } + + fun getSlot(@Nonnull invName: String, slotId: Int): SlotConditionItemHandler? { + val invSlots = inventorySlots[invName] + if (invSlots != null) { + val slot = invSlots.get(slotId) + if (slot.itemHandler.isSlotAvailable(slotId)) { + return slot + } + } + return null + } +} diff --git a/src/main/java/github/kasuminova/novaeng/common/handler/MachineAssemblyHandler.kt b/src/main/java/github/kasuminova/novaeng/common/handler/MachineAssemblyHandler.kt new file mode 100644 index 00000000..385f6598 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/handler/MachineAssemblyHandler.kt @@ -0,0 +1,132 @@ +package github.kasuminova.novaeng.common.handler + +import github.kasuminova.novaeng.NovaEngCoreConfig +import github.kasuminova.novaeng.client.util.NEWBlockArrayPreviewRenderHelper +import github.kasuminova.novaeng.common.item.ItemMachineAssemblyTool +import github.kasuminova.novaeng.common.item.ItemMachineAssemblyTool.getDynamicPatternSize +import github.kasuminova.novaeng.common.util.NEWMachineAssemblyManager +import hellfirepvp.modularmachinery.client.ClientScheduler +import hellfirepvp.modularmachinery.client.util.DynamicMachineRenderContext +import hellfirepvp.modularmachinery.common.block.BlockController +import hellfirepvp.modularmachinery.common.machine.DynamicMachine +import hellfirepvp.modularmachinery.common.tiles.base.TileMultiblockMachineController +import net.minecraft.entity.player.EntityPlayerMP +import net.minecraft.util.EnumActionResult +import net.minecraft.util.EnumFacing +import net.minecraft.util.EnumHand +import net.minecraft.util.text.TextComponentTranslation +import net.minecraftforge.event.entity.player.PlayerInteractEvent +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.PlayerEvent +import net.minecraftforge.fml.common.gameevent.TickEvent + +object MachineAssemblyHandler { + + @SubscribeEvent + fun onPlayerRightBlock(event: PlayerInteractEvent.RightClickBlock) { + val hand = event.hand + if (hand != EnumHand.MAIN_HAND) return + val world = event.world + val player = event.entityPlayer + val stack = player.getHeldItem(hand) + if (!player.isSneaking && stack.item is ItemMachineAssemblyTool) { + val pos = event.pos + val tile = world.getTileEntity(pos) + var state = world.getBlockState(pos) + val block = state.block + @Suppress("DEPRECATION") + state = block.getActualState(state, world, pos) + var facing: EnumFacing? = null + val machine: DynamicMachine = if (tile is TileMultiblockMachineController) { + tile.blueprintMachine ?: if (block is BlockController) + block.getParentMachine() + else return + } else { + val meta = block.getMetaFromState(state) + var m: DynamicMachine? = null + for (entry in NEWMachineAssemblyManager.getConstructorsIterator()) { + if (entry.key == block && entry.value.containsKey(meta)) { + m = entry.value[meta] + val pf = block.blockState.getProperty("facing") + facing = if (pf != null) { + state.getValue(pf) as? EnumFacing ?: event.face + } else event.face + break + } + } + facing = if (facing == EnumFacing.UP || facing == EnumFacing.DOWN) { + EnumFacing.NORTH + } else facing + m ?: return + } + + event.isCanceled = true + event.cancellationResult = EnumActionResult.SUCCESS + + if (world.isRemote) { + if (NEWBlockArrayPreviewRenderHelper.work) { + val oldpos = NEWBlockArrayPreviewRenderHelper.key + NEWBlockArrayPreviewRenderHelper.unloadWorld() + if (oldpos == pos.toLong()) { + return + } + } + val renderContext = DynamicMachineRenderContext + .createContext(machine, getDynamicPatternSize(stack)) + renderContext.shiftSnap = ClientScheduler.getClientTick() + NEWBlockArrayPreviewRenderHelper.startPreview(renderContext, pos, facing) + } + } + } + + @SubscribeEvent(priority = EventPriority.HIGH) + fun onPlayerTick(event: TickEvent.PlayerTickEvent) { + val player = event.player + val world = player.world + if (player is EntityPlayerMP && world.worldTime % NovaEngCoreConfig.MACHINE_ASSEMBLY_TOOL.buildSpeed == 0L) { + val ma = NEWMachineAssemblyManager.getMachineAssembly(player) ?: return + var restart: Boolean + for (i in 0.. { + restart = true + continue + } + + NEWMachineAssemblyManager.OperatingStatus.FAILURE -> { + NEWMachineAssemblyManager.removeMachineAssembly(player) + return + } + + NEWMachineAssemblyManager.OperatingStatus.COMPLETE -> { + player.sendMessage( + TextComponentTranslation( + "message.assembly.tip.success" + ) + ) + NEWMachineAssemblyManager.removeMachineAssembly(player) + return + } + + NEWMachineAssemblyManager.OperatingStatus.SUCCESS -> {} + } + } while (restart) + } + } + } + + @SubscribeEvent + fun onPlayerLogOut(event: PlayerEvent.PlayerLoggedOutEvent) { + NEWMachineAssemblyManager.removeMachineAssembly(event.player) + } + + @SubscribeEvent + fun onPlayerChangeDim(event: PlayerEvent.PlayerChangedDimensionEvent) { + NEWMachineAssemblyManager.removeMachineAssembly(event.player) + } + +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/item/ItemBasic.java b/src/main/java/github/kasuminova/novaeng/common/item/ItemBasic.java deleted file mode 100644 index afd574eb..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/item/ItemBasic.java +++ /dev/null @@ -1,58 +0,0 @@ -package github.kasuminova.novaeng.common.item; - -import github.kasuminova.novaeng.NovaEngineeringCore; -import github.kasuminova.novaeng.common.core.CreativeTabNovaEng; -import github.kasuminova.novaeng.common.enchantment.MagicBreaking; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -public class ItemBasic extends Item { - - public static List NAMES = Arrays.asList( - MagicBreaking.MAGICBREAKING.getId() + "_stone" - ); - protected static Map map = new Object2ObjectOpenHashMap<>(); - - public ItemBasic(final String name) { - this.setMaxStackSize(1); - this.setCreativeTab(CreativeTabNovaEng.INSTANCE); - this.setRegistryName(new ResourceLocation(NovaEngineeringCore.MOD_ID, name)); - this.setTranslationKey(NovaEngineeringCore.MOD_ID + '.' + name); - } - - public static List getAllItem() { - List ItemBasics = new ObjectArrayList<>(); - for (String name : NAMES) { - final ItemBasic item = new ItemBasic(name); - ItemBasics.add(item); - map.put(name, item); - } - return ItemBasics; - } - - public static ItemBasic getItem(String name) { - return map.get(name); - } - - @SideOnly(Side.CLIENT) - @SuppressWarnings("DataFlowIssue") - protected void addCheckedInformation(ItemStack stack, World world, List lines, ITooltipFlag advancedTooltips) { - int i = 0; - while (I18n.hasKey(this.getTranslationKey() + ".tooltip." + i)) { - lines.add(I18n.format(this.getTranslationKey() + ".tooltip." + i)); - i++; - } - } -} diff --git a/src/main/java/github/kasuminova/novaeng/common/item/ItemBasic.kt b/src/main/java/github/kasuminova/novaeng/common/item/ItemBasic.kt new file mode 100644 index 00000000..b38c6d85 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/item/ItemBasic.kt @@ -0,0 +1,58 @@ +package github.kasuminova.novaeng.common.item + +import github.kasuminova.novaeng.NovaEngineeringCore +import github.kasuminova.novaeng.common.core.CreativeTabNovaEng +import github.kasuminova.novaeng.common.enchantment.MagicBreaking +import github.kasuminova.novaeng.common.util.Functions +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import net.minecraft.client.resources.I18n +import net.minecraft.client.util.ITooltipFlag +import net.minecraft.item.Item +import net.minecraft.item.ItemStack +import net.minecraft.util.ResourceLocation +import net.minecraft.world.World +import net.minecraftforge.fml.relauncher.Side +import net.minecraftforge.fml.relauncher.SideOnly + +open class ItemBasic(name: String) : Item() { + + companion object { + var NAMES: List = Functions.asList( + MagicBreaking.MAGICBREAKING.id + "_stone" + ) + + protected var map: MutableMap = Object2ObjectOpenHashMap() + + val allItem: List + get() { + val itemBasics: MutableList = ObjectArrayList() + for (name in NAMES) { + val item = ItemBasic(name) + itemBasics.add(item) + map[name] = item + } + return itemBasics + } + + fun getItem(name: String?): ItemBasic? { + return map[name] + } + } + + init { + this.setMaxStackSize(1) + this.setCreativeTab(CreativeTabNovaEng.INSTANCE) + this.registryName = ResourceLocation(NovaEngineeringCore.MOD_ID, name) + this.translationKey = NovaEngineeringCore.MOD_ID + '.' + name + } + + @SideOnly(Side.CLIENT) + override fun addInformation(stack: ItemStack, world: World?, lines: MutableList, flagIn: ITooltipFlag) { + var i = -1 + while (I18n.hasKey(this.translationKey + ".tooltip." + ++i)) { + lines.add(I18n.format(this.translationKey + ".tooltip." + i)) + } + } + +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/item/ItemMachineAssemblyTool.kt b/src/main/java/github/kasuminova/novaeng/common/item/ItemMachineAssemblyTool.kt new file mode 100644 index 00000000..d21a4c73 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/item/ItemMachineAssemblyTool.kt @@ -0,0 +1,333 @@ +@file:Suppress("DEPRECATION") + +package github.kasuminova.novaeng.common.item + +import appeng.api.networking.crafting.ICraftingGrid +import appeng.util.item.AEItemStack +import com.brandon3055.draconicevolution.api.itemconfig.BooleanConfigField +import com.brandon3055.draconicevolution.api.itemconfig.IConfigurableItem +import com.brandon3055.draconicevolution.api.itemconfig.IItemConfigField +import com.brandon3055.draconicevolution.api.itemconfig.IntegerConfigField +import com.brandon3055.draconicevolution.api.itemconfig.ItemConfigFieldRegistry +import com.brandon3055.draconicevolution.api.itemconfig.ToolConfigHelper +import com.circulation.random_complement.common.interfaces.RCCraftingGridCache +import com.circulation.random_complement.common.util.MEHandler +import github.kasuminova.novaeng.NovaEngineeringCore +import github.kasuminova.novaeng.common.CommonProxy +import github.kasuminova.novaeng.common.util.AssemblyBlockArray +import github.kasuminova.novaeng.common.util.AutoCraftingQueue +import github.kasuminova.novaeng.common.util.NEWMachineAssemblyManager +import hellfirepvp.modularmachinery.common.block.BlockController +import hellfirepvp.modularmachinery.common.machine.DynamicMachine +import hellfirepvp.modularmachinery.common.machine.MachineRegistry +import hellfirepvp.modularmachinery.common.tiles.base.TileMultiblockMachineController +import hellfirepvp.modularmachinery.common.util.BlockArrayCache +import ink.ikx.mmce.common.utils.StructureIngredient +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import net.minecraft.client.util.ITooltipFlag +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.item.ItemStack +import net.minecraft.util.ActionResult +import net.minecraft.util.EnumActionResult +import net.minecraft.util.EnumFacing +import net.minecraft.util.EnumHand +import net.minecraft.util.math.BlockPos +import net.minecraft.util.text.TextComponentTranslation +import net.minecraft.util.text.translation.I18n +import net.minecraft.world.World +import net.minecraftforge.fml.relauncher.Side +import net.minecraftforge.fml.relauncher.SideOnly +import java.util.ArrayDeque +import kotlin.math.max +import kotlin.math.min + +object ItemMachineAssemblyTool : ItemBasic("machine_assembly_tool"), IConfigurableItem { + + override fun onItemRightClick(world: World, player: EntityPlayer, hand: EnumHand): ActionResult { + if (hand != EnumHand.MAIN_HAND) return super.onItemRightClick(world, player, hand) + if (world.isRemote) { + player.openGui( + NovaEngineeringCore.instance, + CommonProxy.GuiType.MACHINE_ASSEMBLY_TOOL.ordinal, + world, + 0, + 0, + 0 + ) + } + return ActionResult(EnumActionResult.SUCCESS, player.getHeldItem(hand)) + } + + override fun onItemUse( + player: EntityPlayer, world: World, pos: BlockPos, hand: EnumHand, + facing: EnumFacing, hitX: Float, hitY: Float, hitZ: Float + ): EnumActionResult { + if (hand != EnumHand.MAIN_HAND || world.isRemote) return EnumActionResult.PASS + val tile = world.getTileEntity(pos) + if (tile == null) { + return EnumActionResult.PASS + } else if (player.isSneaking) { + if (!NEWMachineAssemblyManager.checkMachineAssembly(player)) { + var state = world.getBlockState(pos) + val block = state.block + @Suppress("DEPRECATION") + state = block.getActualState(state, world, pos) + val machine: DynamicMachine + val controllerFacing: EnumFacing + if (tile is TileMultiblockMachineController) { + machine = tile.blueprintMachine ?: if (block is BlockController) + block.getParentMachine() + else return EnumActionResult.FAIL + controllerFacing = player.world.getBlockState(pos).getValue(BlockController.FACING) + } else { + val meta = block.getMetaFromState(state) + var m: DynamicMachine? = null + var e: EnumFacing? = null + for (entry in NEWMachineAssemblyManager.getConstructorsIterator()) { + if (entry.key == block && entry.value.containsKey(meta)) { + m = entry.value[meta] + val pf = block.blockState.getProperty("facing") + e = if (pf != null) { + state.getValue(pf) as? EnumFacing ?: facing + } else facing + break + } + } + e = if (e == EnumFacing.UP || e == EnumFacing.DOWN) { + EnumFacing.NORTH + } else e + machine = m ?: return EnumActionResult.FAIL + controllerFacing = e ?: return EnumActionResult.FAIL + } + + val stack = player.getHeldItem(hand) + var array = AssemblyBlockArray( + BlockArrayCache.getBlockArrayCache( + machine.pattern, + controllerFacing + ) + ) + + var dynamicPatternSize = getDynamicPatternSize(stack) + val dynamicPatterns = machine.dynamicPatterns + + for (pattern in dynamicPatterns.values) { + dynamicPatternSize = max(dynamicPatternSize, pattern.minSize) + } + + for (pattern in dynamicPatterns.values) { + pattern.addPatternToBlockArray( + array, + min(max(pattern.minSize, dynamicPatternSize), pattern.maxSize), + pattern.faces.iterator().next(), + controllerFacing + ) + } + + val st = StructureIngredient.of(player.world, pos, array.copy()) + array = array.offset(pos) + if (array.min.y < 0 || array.max.y > 255) { + player.sendMessage( + TextComponentTranslation( + "message.assembly.tip.too_high", + if (array.min.y < 1) { + "y = ${array.min.y}" + } else { + "y = ${array.max.y}" + } + ) + ) + return EnumActionResult.FAIL + } + + val usingAE = isUsingAE(stack) + val autoAECrafting = usingAE && isAutoAECrafting(stack) + val missing = NEWMachineAssemblyManager.checkAllItems(player, st, usingAE, autoAECrafting) + val q = missing.list + if (autoAECrafting && !q.isEmpty()) { + MEHandler.getTerminalGuiObject(player)?.actionableNode?.grid?.let { + val autoList = ArrayDeque() + val cgc: RCCraftingGridCache = it.getCache(ICraftingGrid::class.java) + val list = cgc.`rc$getCraftableItems`() + for (stacks in q) { + for (item in stacks) { + if (item.isEmpty) continue + if (list.containsKey(AEItemStack.fromItemStack(item))) { + autoList.add(item) + break + } + } + } + AutoCraftingQueue.setQueueAndStrat(autoList, player) + } + } + if (q.isEmpty() + || !isNeedAllIngredient(stack) + ) { + array = NEWMachineAssemblyManager.addAssemblyMachine(player, array) + array.usingAE = usingAE + array.ignoreFluids = isIgnoreFluids(stack) + array.missing = missing.miss + array.start() + player.sendMessage( + TextComponentTranslation( + "message.assembly.tip.already_assembly.start" + ) + ) + return EnumActionResult.SUCCESS + } + } else { + player.sendMessage( + TextComponentTranslation( + "message.assembly.tip.already_assembly" + ) + ) + return EnumActionResult.FAIL + } + } + return EnumActionResult.PASS + } + + @SideOnly(Side.CLIENT) + override fun addInformation(stack: ItemStack, world: World?, lines: MutableList, flagIn: ITooltipFlag) { + super.addInformation(stack, world, lines, flagIn) + lines.add("item.novaeng_core.machine_assembly_tool.config".i18n()) + lines.add(" ${usingAEConfig.unlocalizedName.i18n()} : ${isUsingAE(stack)}") + lines.add(" ${ignoreFluidsConfig.unlocalizedName.i18n()} : ${isIgnoreFluids(stack)}") + lines.add(" ${dynamicPatternSizeConfig.unlocalizedName.i18n()} : ${getDynamicPatternSize(stack)}") + lines.add(" ${autoAECraftingConfig.unlocalizedName.i18n()} : ${isAutoAECrafting(stack)}") + lines.add(" ${needAllIngredientConfig.unlocalizedName.i18n()} : ${isNeedAllIngredient(stack)}") + } + + fun isUsingAE(stack: ItemStack): Boolean { + return ToolConfigHelper.getFieldStorage(stack).getBoolean("UsingAE") + } + + fun isIgnoreFluids(stack: ItemStack): Boolean { + return ToolConfigHelper.getFieldStorage(stack).getBoolean("IgnoreFluids") + } + + fun getDynamicPatternSize(stack: ItemStack): Int { + return ToolConfigHelper.getFieldStorage(stack).getInteger("DynamicPatternSize") + } + + fun isAutoAECrafting(stack: ItemStack): Boolean { + return ToolConfigHelper.getFieldStorage(stack).getBoolean("AutoAECrafting") + } + + fun isNeedAllIngredient(stack: ItemStack): Boolean { + return ToolConfigHelper.getFieldStorage(stack).getBoolean("NeedAllIngredient") + } + + fun setUsingAE(stack: ItemStack, b: Boolean) { + ToolConfigHelper.getFieldStorage(stack).setBoolean("UsingAE", b) + } + + fun setIgnoreFluids(stack: ItemStack, b: Boolean) { + ToolConfigHelper.getFieldStorage(stack).setBoolean("IgnoreFluids", b) + } + + fun setDynamicPatternSize(stack: ItemStack, size: Int) { + ToolConfigHelper.getFieldStorage(stack).setByte("DynamicPatternSize", size.toByte()) + } + + fun setAutoAECrafting(stack: ItemStack, auto: Boolean) { + ToolConfigHelper.getFieldStorage(stack).setBoolean("AutoAECrafting", auto) + } + + fun setNeedAllIngredient(stack: ItemStack, auto: Boolean) { + ToolConfigHelper.getFieldStorage(stack).setBoolean("NeedAllIngredient", auto) + } + + val usingAEConfig by lazy { + BooleanConfigField( + "UsingAE", + false, + "UsingAE".getDescription() + ) + } + + val ignoreFluidsConfig by lazy { + BooleanConfigField( + "IgnoreFluids", + false, + "IgnoreFluids".getDescription() + ) + } + + val dynamicPatternSizeConfig by lazy { + IntegerConfigField( + "DynamicPatternSize", + 0, + 0, + getMaxDynamicPatternSize(), + "DynamicPatternSize".getDescription(), + IItemConfigField.EnumControlType.SELECTIONS + ) + } + + val autoAECraftingConfig by lazy { + BooleanConfigField( + "AutoAECrafting", + false, + "AutoAECrafting".getDescription() + ) + } + + val needAllIngredientConfig by lazy { + BooleanConfigField( + "NeedAllIngredient", + false, + "NeedAllIngredient".getDescription() + ) + } + + override fun getFields( + stack: ItemStack, + registry: ItemConfigFieldRegistry + ): ItemConfigFieldRegistry { + registry.register(stack, usingAEConfig) + registry.register(stack, ignoreFluidsConfig) + registry.register(stack, dynamicPatternSizeConfig) + registry.register(stack, autoAECraftingConfig) + registry.register(stack, needAllIngredientConfig) + + return registry + } + + override fun onFieldChanged(stack: ItemStack, field: IItemConfigField) { + + } + + override fun getProfileCount(stack: ItemStack): Int { + return 5 + } + + private fun String.getDescription(): String { + return "text.machine_assembly_tool.config.$this".i18n() + } + + private fun String.i18n(): String { + return I18n.translateToLocal(this) + } + + private fun String.i18n(vararg objs: Any): String { + return I18n.translateToLocalFormatted(this, objs) + } + + private fun getMaxDynamicPatternSize(): Int { + val list = ObjectArrayList(MachineRegistry.getLoadedMachines()) + list.addAll(NEWMachineAssemblyManager.getAllDynamicMachines()) + + return list.parallelStream() + .mapToInt { + it.dynamicPatterns.values.stream() + .mapToInt { it1 -> it1.maxSize } + .max() + .orElse(1) + } + .max() + .orElse(1) + } + +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/machine/DreamEnergyCore.java b/src/main/java/github/kasuminova/novaeng/common/machine/DreamEnergyCore.java index 27a2d78c..87f8a809 100644 --- a/src/main/java/github/kasuminova/novaeng/common/machine/DreamEnergyCore.java +++ b/src/main/java/github/kasuminova/novaeng/common/machine/DreamEnergyCore.java @@ -8,6 +8,7 @@ import github.kasuminova.mmce.common.event.machine.MachineTickEvent; import github.kasuminova.mmce.common.helper.IMachineController; import github.kasuminova.novaeng.common.tile.TileDreamEnergyPort; +import github.kasuminova.novaeng.common.util.BlockPos2ValueMap; import github.kasuminova.novaeng.common.util.FixedSizeDeque; import github.kasuminova.novaeng.common.util.IBlockPosEx; import hellfirepvp.modularmachinery.ModularMachinery; @@ -26,6 +27,7 @@ import stanhebben.zenscript.annotations.ZenMethod; import java.math.BigInteger; +import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -170,7 +172,8 @@ public static BigInteger getBigInt(String num) { } private static FixedSizeDeque getEnergyInfo(World world, BlockPos pos) { - return map.computeIfAbsent(world, k -> new ConcurrentHashMap<>()) + return map.computeIfAbsent(world, k -> + Collections.synchronizedMap(new BlockPos2ValueMap<>())) .computeIfAbsent(pos, m -> new FixedSizeDeque<>(MinuteScale)); } diff --git a/src/main/java/github/kasuminova/novaeng/common/network/PktAutoCraftConfirm.kt b/src/main/java/github/kasuminova/novaeng/common/network/PktAutoCraftConfirm.kt new file mode 100644 index 00000000..64cdfbb1 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/network/PktAutoCraftConfirm.kt @@ -0,0 +1,33 @@ +package github.kasuminova.novaeng.common.network + +import github.kasuminova.novaeng.common.container.ContainerNEWCraftConfirm +import github.kasuminova.novaeng.common.util.AutoCraftingQueue +import io.netty.buffer.ByteBuf +import net.minecraftforge.fml.common.network.simpleimpl.IMessage +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext + +class PktAutoCraftConfirm : IMessage, IMessageHandler { + override fun fromBytes(buf: ByteBuf) { + + } + + override fun toBytes(buf: ByteBuf) { + + } + + override fun onMessage( + message: PktAutoCraftConfirm, + ctx: MessageContext + ): IMessage? { + val player = ctx.serverHandler.player + if (player.openContainer is ContainerNEWCraftConfirm) { + AutoCraftingQueue.getQueue(player)?.let { + if (!it.executionQueue(player)) { + player.closeContainer() + } + } + } + return null + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/network/PktEFabricatorGUIData.java b/src/main/java/github/kasuminova/novaeng/common/network/PktEFabricatorGUIData.java index d4a431cb..2ff78cde 100644 --- a/src/main/java/github/kasuminova/novaeng/common/network/PktEFabricatorGUIData.java +++ b/src/main/java/github/kasuminova/novaeng/common/network/PktEFabricatorGUIData.java @@ -24,8 +24,8 @@ public class PktEFabricatorGUIData implements IMessage, IMessageHandler>(5) + var u = -1 + for (i in -2..2) { + val pos = arrayOfNulls(5) + var j = -1 + for (k in -2..2) { + pos[++j] = XY(i, k) + } + p[++u] = pos as Array + } + /** + * X X X X X + * X X X X X + * X X X X X + * X X X X X + * X X X X X + */ + val poss = p as Array> + + mekReactor.addBlock(BlockPos.ORIGIN, packBlock(reactor.blockState)) + + mekReactor.addBlock(poss[0][2][0], framework) + mekReactor.addBlock(poss[1][1][0], framework) + mekReactor.addBlock(poss[1][2][0], functional) + mekReactor.addBlock(poss[1][3][0], framework) + mekReactor.addBlock(poss[2][0][0], framework) + mekReactor.addBlock(poss[2][1][0], functional) + mekReactor.addBlock(poss[2][3][0], functional) + mekReactor.addBlock(poss[2][4][0], framework) + mekReactor.addBlock(poss[3][1][0], framework) + mekReactor.addBlock(poss[3][2][0], functional) + mekReactor.addBlock(poss[3][3][0], framework) + mekReactor.addBlock(poss[4][2][0], framework) + mekReactor.addBlock(poss[0][1][-1], framework) + mekReactor.addBlock(poss[0][2][-1], functional) + mekReactor.addBlock(poss[0][3][-1], framework) + mekReactor.addBlock(poss[1][0][-1], framework) + mekReactor.addBlock(poss[1][4][-1], framework) + mekReactor.addBlock(poss[2][0][-1], functional) + mekReactor.addBlock(poss[2][4][-1], functional) + mekReactor.addBlock(poss[3][0][-1], framework) + mekReactor.addBlock(poss[3][4][-1], framework) + mekReactor.addBlock(poss[4][1][-1], framework) + mekReactor.addBlock(poss[4][2][-1], functional) + mekReactor.addBlock(poss[4][3][-1], framework) + mekReactor.addBlock(poss[0][0][-2], framework) + mekReactor.addBlock(poss[0][1][-2], functional) + mekReactor.addBlock(poss[0][2][-2], center) + mekReactor.addBlock(poss[0][3][-2], functional) + mekReactor.addBlock(poss[0][4][-2], framework) + mekReactor.addBlock(poss[1][0][-2], functional) + mekReactor.addBlock(poss[1][4][-2], functional) + mekReactor.addBlock(poss[2][0][-2], center) + mekReactor.addBlock(poss[2][4][-2], center) + mekReactor.addBlock(poss[3][0][-2], functional) + mekReactor.addBlock(poss[3][4][-2], functional) + mekReactor.addBlock(poss[4][0][-2], framework) + mekReactor.addBlock(poss[4][1][-2], functional) + mekReactor.addBlock(poss[4][2][-2], center) + mekReactor.addBlock(poss[4][3][-2], functional) + mekReactor.addBlock(poss[4][4][-2], framework) + mekReactor.addBlock(poss[0][1][-3], framework) + mekReactor.addBlock(poss[0][2][-3], functional) + mekReactor.addBlock(poss[0][3][-3], framework) + mekReactor.addBlock(poss[1][0][-3], framework) + mekReactor.addBlock(poss[1][4][-3], framework) + mekReactor.addBlock(poss[2][0][-3], functional) + mekReactor.addBlock(poss[2][4][-3], functional) + mekReactor.addBlock(poss[3][0][-3], framework) + mekReactor.addBlock(poss[3][4][-3], framework) + mekReactor.addBlock(poss[4][1][-3], framework) + mekReactor.addBlock(poss[4][2][-3], functional) + mekReactor.addBlock(poss[4][3][-3], framework) + mekReactor.addBlock(poss[0][2][-4], framework) + mekReactor.addBlock(poss[1][1][-4], framework) + mekReactor.addBlock(poss[1][2][-4], functional) + mekReactor.addBlock(poss[1][3][-4], framework) + mekReactor.addBlock(poss[2][0][-4], framework) + mekReactor.addBlock(poss[2][1][-4], functional) + mekReactor.addBlock(poss[2][2][-4], functional) + mekReactor.addBlock(poss[2][3][-4], functional) + mekReactor.addBlock(poss[2][4][-4], framework) + mekReactor.addBlock(poss[3][1][-4], framework) + mekReactor.addBlock(poss[3][2][-4], functional) + mekReactor.addBlock(poss[3][3][-4], framework) + mekReactor.addBlock(poss[4][2][-4], framework) + + NEWMachineAssemblyManager.setConstructors( + reactor, + reactorMachine.setName("tile.Reactor.name") + ) + + val thermalEvaporationMachine = NEWDynamicMachine("") + if (thermalEvaporationMachine is AccessorAbstractMachine) { + thermalEvaporationMachine.setRL(ResourceLocation("mek", "thermalEvaporation".camelToSnake())) + } + val thermalEvaporationArray = thermalEvaporationMachine.pattern + val thermalEvaporation = NEWMachineAssemblyManager.BlockPair(MekanismBlocks.BasicBlock, 14) + val thermal = packBlock(MekanismBlocks.BasicBlock2.defaultState) + val thermalP = + packBlock(MekanismBlocks.BasicBlock2.defaultState, MekanismBlocks.BasicBlock.getStateFromMeta(15)) + + thermalEvaporationArray.addBlock(-1, -1, 3, thermal) + thermalEvaporationArray.addBlock(0, -1, 3, thermal) + thermalEvaporationArray.addBlock(1, -1, 3, thermal) + thermalEvaporationArray.addBlock(-2, -1, 3, thermal) + thermalEvaporationArray.addBlock(-1, -1, 2, thermal) + thermalEvaporationArray.addBlock(0, -1, 2, thermal) + thermalEvaporationArray.addBlock(1, -1, 2, thermal) + thermalEvaporationArray.addBlock(-2, -1, 2, thermal) + thermalEvaporationArray.addBlock(-1, -1, 1, thermal) + thermalEvaporationArray.addBlock(0, -1, 1, thermal) + thermalEvaporationArray.addBlock(1, -1, 1, thermal) + thermalEvaporationArray.addBlock(-2, -1, 1, thermal) + thermalEvaporationArray.addBlock(-1, -1, 0, thermal) + thermalEvaporationArray.addBlock(0, -1, 0, thermal) + thermalEvaporationArray.addBlock(1, -1, 0, thermal) + thermalEvaporationArray.addBlock(-2, -1, 0, thermal) + + thermalEvaporationArray.addBlock(-1, 0, 0, thermalP) + thermalEvaporationArray.addBlock(BlockPos.ORIGIN, packBlock(thermalEvaporation.blockState)) + thermalEvaporationArray.addBlock(1, 0, 0, thermalP) + thermalEvaporationArray.addBlock(-2, 0, 0, thermalP) + thermalEvaporationArray.addBlock(-1, 0, 3, thermalP) + thermalEvaporationArray.addBlock(0, 0, 3, thermalP) + thermalEvaporationArray.addBlock(1, 0, 3, thermalP) + thermalEvaporationArray.addBlock(-2, 0, 3, thermalP) + thermalEvaporationArray.addBlock(1, 0, 2, thermalP) + thermalEvaporationArray.addBlock(1, 0, 1, thermalP) + thermalEvaporationArray.addBlock(-2, 0, 2, thermalP) + thermalEvaporationArray.addBlock(-2, 0, 1, thermalP) + + val dy = DynamicPattern("thermal", TaggedPositionBlockArray(), TaggedPositionBlockArray(), 1, 16) + dy.faces.add(EnumFacing.UP) + dy.structureSizeOffset = dy.structureSizeOffset.add(0, 1, 0) + + val patter = dy.pattern + patter.addBlock(-1, 1, 0, thermalP) + patter.addBlock(0, 1, 0, thermalP) + patter.addBlock(1, 1, 0, thermalP) + patter.addBlock(-2, 1, 0, thermalP) + patter.addBlock(-1, 1, 3, thermalP) + patter.addBlock(0, 1, 3, thermalP) + patter.addBlock(1, 1, 3, thermalP) + patter.addBlock(-2, 1, 3, thermalP) + patter.addBlock(1, 1, 2, thermalP) + patter.addBlock(1, 1, 1, thermalP) + patter.addBlock(-2, 1, 2, thermalP) + patter.addBlock(-2, 1, 1, thermalP) + + val patterEnd = dy.patternEnd + patterEnd.addBlock(-1, 0, 0, thermalP) + patterEnd.addBlock(BlockPos.ORIGIN, thermalP) + patterEnd.addBlock(1, 0, 0, thermalP) + patterEnd.addBlock(-2, 0, 0, thermalP) + patterEnd.addBlock(-1, 0, 3, thermalP) + patterEnd.addBlock(0, 0, 3, thermalP) + patterEnd.addBlock(1, 0, 3, thermalP) + patterEnd.addBlock(-2, 0, 3, thermalP) + patterEnd.addBlock(1, 0, 2, thermalP) + patterEnd.addBlock(1, 0, 1, thermalP) + patterEnd.addBlock(-2, 0, 2, thermalP) + patterEnd.addBlock(-2, 0, 1, thermalP) + + thermalEvaporationMachine.addDynamicPattern("thermal", dy) + + NEWMachineAssemblyManager.setConstructors( + thermalEvaporation, + thermalEvaporationMachine.setName("tile.ThermalEvaporation.name") + ) + } + + private fun regBot() { + val terraPlateMachine = NEWDynamicMachine("") + if (terraPlateMachine is AccessorAbstractMachine) { + terraPlateMachine.setRL(ResourceLocation("botania", "terra_plate")) + } + val terraplateArray = terraPlateMachine.pattern + val stone = packBlock(ModBlocks.livingrock.defaultState) + val lapis = packBlock(Blocks.LAPIS_BLOCK.defaultState) + val terraPlate = NEWMachineAssemblyManager.BlockPair(ModBlocks.terraPlate, 0) + + terraplateArray.addBlock(BlockPos.ORIGIN, packBlock(terraPlate.blockState)) + terraplateArray.addBlock(0, -1, 0, stone) + terraplateArray.addBlock(-1, -1, -1, stone) + terraplateArray.addBlock(-1, -1, 1, stone) + terraplateArray.addBlock(1, -1, -1, stone) + terraplateArray.addBlock(1, -1, 1, stone) + terraplateArray.addBlock(0, -1, 1, lapis) + terraplateArray.addBlock(0, -1, -1, lapis) + terraplateArray.addBlock(1, -1, 0, lapis) + terraplateArray.addBlock(-1, -1, 0, lapis) + + NEWMachineAssemblyManager.setConstructors( + terraPlate, + terraPlateMachine.setName("tile.botania:terraPlate.name") + ) + + val alfheimportalMachine = NEWDynamicMachine("") + if (alfheimportalMachine is AccessorAbstractMachine) { + alfheimportalMachine.setRL(ResourceLocation("botania", "alfheimportal")) + } + val alfheimportalArray = alfheimportalMachine.pattern + val wood = packBlock(ModBlocks.livingwood.defaultState) + val lightwood = packBlock(ModBlocks.livingwood.getStateFromMeta(5)) + val alfheimportal = NEWMachineAssemblyManager.BlockPair(ModBlocks.alfPortal, 0) + + alfheimportalArray.addBlock(BlockPos.ORIGIN, packBlock(alfheimportal.blockState)) + alfheimportalArray.addBlock(1, 0, 0, wood) + alfheimportalArray.addBlock(-1, 0, 0, wood) + alfheimportalArray.addBlock(2, 1, 0, wood) + alfheimportalArray.addBlock(-2, 1, 0, wood) + alfheimportalArray.addBlock(2, 2, 0, lightwood) + alfheimportalArray.addBlock(-2, 2, 0, lightwood) + alfheimportalArray.addBlock(2, 3, 0, wood) + alfheimportalArray.addBlock(-2, 3, 0, wood) + alfheimportalArray.addBlock(0, 4, 0, lightwood) + alfheimportalArray.addBlock(1, 4, 0, wood) + alfheimportalArray.addBlock(-1, 4, 0, wood) + + NEWMachineAssemblyManager.setConstructors( + alfheimportal, + alfheimportalMachine.setName("tile.botania:alfheimPortal.name") + ) + } + + private class XY(val x: Int, val z: Int) { + operator fun get(y: Int): BlockPos { + return BlockPos(x, y, z) + } + } + + private fun transformationBlockArrays(array: PatternBlockArray, name: String): NEWDynamicMachine { + val machine = NEWDynamicMachine("") + if (machine is AccessorAbstractMachine) { + machine.setRL(ResourceLocation("astralsorcery", name)) + } + val newBlcokArray = machine.pattern + for (entry in array.pattern) { + val info = BlockArray.BlockInformation(ObjectLists.singleton(IBlockStateDescriptor(entry.value.state))) + newBlcokArray.addBlock(entry.key, info) + } + return machine + } + + private fun NEWDynamicMachine.setName(name: String): NEWDynamicMachine { + this.localizedName = I18n.translateToLocal(name) + return this + } + + /** + * @param this 驼峰结构的字符串 + * @return 蛇形结构的字符串 + */ + private fun String.camelToSnake(): String { + val len = this.length + val buffer = CharArray(len * 2) + var index = 0 + var prevWasLower = false + + for (i in 0.. event) { ITEMS_TO_REGISTER.add(ItemHorologiumCompass.INSTANCE); } - ITEMS_TO_REGISTER.addAll(ItemBasic.getAllItem()); + ITEMS_TO_REGISTER.addAll(ItemBasic.Companion.getAllItem()); + ITEMS_TO_REGISTER.add(ItemMachineAssemblyTool.INSTANCE); registerItems(); diff --git a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorController.java b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorController.java deleted file mode 100644 index 7a205a5d..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorController.java +++ /dev/null @@ -1,630 +0,0 @@ -package github.kasuminova.novaeng.common.tile.ecotech.efabricator; - -import appeng.api.AEApi; -import appeng.api.config.Actionable; -import appeng.api.config.PowerMultiplier; -import appeng.api.networking.energy.IEnergyGrid; -import appeng.api.storage.IMEMonitor; -import appeng.api.storage.channels.IItemStorageChannel; -import appeng.api.storage.data.IAEItemStack; -import appeng.api.storage.data.IItemList; -import appeng.me.GridAccessException; -import appeng.me.helpers.AENetworkProxy; -import appeng.tile.inventory.AppEngInternalInventory; -import appeng.util.Platform; -import appeng.util.item.ItemList; -import github.kasuminova.mmce.client.util.ItemStackUtils; -import github.kasuminova.mmce.common.helper.IDynamicPatternInfo; -import github.kasuminova.novaeng.NovaEngineeringCore; -import github.kasuminova.novaeng.client.util.BlockModelHider; -import github.kasuminova.novaeng.common.block.ecotech.efabricator.BlockEFabricatorController; -import github.kasuminova.novaeng.common.block.ecotech.efabricator.prop.Levels; -import github.kasuminova.novaeng.common.network.PktEFabricatorGUIData; -import github.kasuminova.novaeng.common.tile.ecotech.EPartController; -import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorParallelProc.Modifier; -import github.kasuminova.novaeng.common.util.MachineCoolants; -import hellfirepvp.modularmachinery.ModularMachinery; -import hellfirepvp.modularmachinery.client.ClientProxy; -import hellfirepvp.modularmachinery.common.machine.MachineRegistry; -import hellfirepvp.modularmachinery.common.util.ItemUtils; -import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap; -import lombok.Getter; -import net.minecraft.block.Block; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.common.util.Constants; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidTankProperties; -import net.minecraftforge.fml.common.FMLCommonHandler; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static github.kasuminova.novaeng.common.block.ecotech.efabricator.BlockEFabricatorController.L4; -import static github.kasuminova.novaeng.common.block.ecotech.efabricator.BlockEFabricatorController.L6; -import static github.kasuminova.novaeng.common.block.ecotech.efabricator.BlockEFabricatorController.L9; - -@SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized", "unused"}) -public class EFabricatorController extends EPartController { - - public static final int MAX_COOLANT_CACHE = 100_000; - public static final int WORK_DELAY = 20; - - public static final List HIDE_POS_LIST = Arrays.asList( - // Center - new BlockPos(0, 1, 0), - new BlockPos(0, -1, 0), - - new BlockPos(0, 1, 1), - new BlockPos(0, 0, 1), - new BlockPos(0, -1, 1), - - // Left - new BlockPos(1, 1, 0), - new BlockPos(1, 0, 0), - new BlockPos(1, -1, 0), - - new BlockPos(1, 1, 1), - new BlockPos(1, 0, 1), - new BlockPos(1, -1, 1), - - // Right - new BlockPos(-1, 1, 0), - new BlockPos(-1, 0, 0), - new BlockPos(-1, -1, 0), - - new BlockPos(-1, 1, 1), - new BlockPos(-1, 0, 1), - new BlockPos(-1, -1, 1) - ); - - protected final List coolantInputHandlers = new ArrayList<>(); - protected final List coolantOutputHandlers = new ArrayList<>(); - - protected final IItemStorageChannel itemChannel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class); - @Getter - protected IItemList outputBuffer = new ItemList(); - - @Getter - protected BlockEFabricatorController parentController = null; - protected double idleDrain = 64; - - @Getter - protected EFabricatorMEChannel channel = null; - - @Getter - protected int length = 0; - - protected int workDelay = WORK_DELAY; - protected int maxWorkDelay = WORK_DELAY; - - @Getter - protected int parallelism = 0; - protected int consumedParallelism = 0; - - @Getter - protected int coolantCache = 0; - - @Getter - protected long totalCrafted = 0; - - protected boolean speedupApplied = false; - @Getter - protected boolean overclocked = false; - @Getter - protected boolean activeCooling = false; - - protected PktEFabricatorGUIData guiDataPacket = null; - protected volatile boolean guiDataDirty = false; - - public EFabricatorController(final ResourceLocation machineRegistryName) { - this(); - this.parentMachine = MachineRegistry.getRegistry().getMachine(machineRegistryName); - this.parentController = BlockEFabricatorController.REGISTRY.get(new ResourceLocation(NovaEngineeringCore.MOD_ID, machineRegistryName.getPath())); - } - - public EFabricatorController() { - this.workMode = WorkMode.SEMI_SYNC; - } - - protected boolean onSyncTick() { - if (channel == null || !channel.getProxy().isActive()) { - this.tickExecutor = null; - return false; - } - - workDelay--; - if (workDelay > 0) { - this.tickExecutor = null; - return false; - } - workDelay = maxWorkDelay; - speedupApplied = false; - clearOutputBuffer(); - supplyWorkerPower(); - supplyCoolantCache(); - return true; - } - - protected void onAsyncTick() { - updateGUIDataPacket(); - - long prevTotalCrafted = totalCrafted; - List workers = getWorkers(); - workers.forEach(worker -> worker.updateStatus(false)); - for (EFabricatorWorker worker : workers) { - if (worker.hasWork()) { - int worked = worker.doWork(); - totalCrafted += worked; - consumedParallelism += worked <= 1 ? 0 : worked; - } - } - if (activeCooling && hasWork()) { - convertOverflowParallelismToWorkDelay(parallelism - consumedParallelism); - } - consumedParallelism = 0; - - if (prevTotalCrafted != totalCrafted) { - markNoUpdateSync(); - } - } - - protected void supplyCoolantCache() { - if (coolantCache >= MAX_COOLANT_CACHE) { - return; - } - - // 写了一坨大的! - for (final IFluidHandler inputHandler : coolantInputHandlers) { - for (final IFluidTankProperties property : inputHandler.getTankProperties()) { - FluidStack contents = property.getContents(); - if (contents == null || contents.amount == 0) { - continue; - } - - MachineCoolants.Coolant coolant = MachineCoolants.INSTANCE.getCoolant(contents.getFluid()); - if (coolant == null) { - continue; - } - - for (final IFluidHandler outputHandler : coolantOutputHandlers) { - int maxCanConsume = coolant.maxCanConsume(inputHandler, outputHandler); - if (maxCanConsume <= 0) { - continue; - } - - int required = MAX_COOLANT_CACHE - coolantCache; - int mul = required / coolant.coolantUnit(); - if (mul * coolant.coolantUnit() < required) { - mul++; - } - mul = Math.min(mul, maxCanConsume); - - if (mul > 0) { - FluidStack input = coolant.input(); - inputHandler.drain(new FluidStack(input, mul * input.amount), true); - FluidStack output = coolant.output(); - if (output != null) { - outputHandler.fill(new FluidStack(output, mul * output.amount), true); - } - coolantCache += mul * coolant.coolantUnit(); - if (coolantCache >= MAX_COOLANT_CACHE) { - return; - } - } - } - } - } - } - - protected void supplyWorkerPower() { - IEnergyGrid energy; - try { - energy = channel.getProxy().getEnergy(); - } catch (GridAccessException ignored) { - return; - } - - for (EFabricatorWorker worker : getWorkers()) { - if (worker.getEnergyCache() < worker.getMaxEnergyCache()) { - worker.supplyEnergy( - (int) energy.extractAEPower(worker.getMaxEnergyCache() - worker.getEnergyCache(), Actionable.MODULATE, PowerMultiplier.CONFIG)); - } - } - } - - protected void clearOutputBuffer() { - try { - AENetworkProxy proxy = this.channel.getProxy(); - IMEMonitor inv = proxy.getStorage().getInventory(itemChannel); - for (final IAEItemStack stack : outputBuffer) { - IAEItemStack notInserted = Platform.poweredInsert(proxy.getEnergy(), inv, stack.copy(), this.channel.getSource()); - if (notInserted != null) { - stack.setStackSize(notInserted.getStackSize()); - } else { - stack.setStackSize(0); - } - } - } catch (GridAccessException ignored) { - } - } - - @Override - protected void updateComponents() { - super.updateComponents(); - IDynamicPatternInfo workers = getDynamicPattern("workers"); - this.length = workers != null ? workers.getSize() : 0; - this.foundComponents.values().forEach(component -> { - if (component.providedComponent() instanceof IFluidHandler handler) { - switch (component.getComponent().ioType) { - case INPUT -> coolantInputHandlers.add(handler); - case OUTPUT -> coolantOutputHandlers.add(handler); - } - } - }); - updateParallelism(); - updateWorkDelay(); - } - - @Override - protected void onAddPart(final EFabricatorPart part) { - if (part instanceof EFabricatorMEChannel channelc) { - this.channel = channelc; - } - } - - protected void clearParts() { - super.clearParts(); - this.coolantInputHandlers.clear(); - this.coolantOutputHandlers.clear(); - this.channel = null; - this.length = 0; - } - - protected void updateParallelism() { - final double[] parallelism = {0}; - Map> modifierMap = getParallelProcs().stream() - .flatMap(proc -> overclocked ? Stream.concat(proc.modifiers.stream(), proc.overclockModifiers.stream()) : proc.modifiers.stream()) // 超频额外添加超频修正器 - .filter(modifier -> modifier.isBuff() || !activeCooling) // 主动冷却移除超频的负面效果。 - .collect(Collectors.groupingBy( - Modifier::type, - () -> new Object2ObjectAVLTreeMap<>(Comparator.comparingInt(EFabricatorParallelProc.Type::getPriority)), - Collectors.toList()) - ); - - modifierMap.values().stream() - .flatMap(Collection::stream) - .filter(Modifier::isBuff) - .forEach(modifier -> parallelism[0] = modifier.apply(parallelism[0])); - modifierMap.values().stream() - .flatMap(Collection::stream) - .filter(Modifier::debuff) - .forEach(modifier -> parallelism[0] = modifier.apply(parallelism[0])); - - this.parallelism = (int) Math.round(parallelism[0]); - } - - public synchronized void convertOverflowParallelismToWorkDelay(final int overflow) { - if (overflow <= 0 || speedupApplied) { - return; - } - float ratio = (float) parallelism / overflow; - int speedUp = Math.min(Math.round(ratio / 0.05f), maxWorkDelay - 1); - - double coolantUsage = parallelism * 0.04; - int maxCanConsume = (int) (coolantCache / coolantUsage); - speedUp = Math.min(speedUp, maxCanConsume); - coolantCache -= (int) Math.round(speedUp * coolantUsage); - - this.workDelay = maxWorkDelay - speedUp; - this.speedupApplied = true; - } - - public void updateWorkDelay() { - if (activeCooling) { - this.maxWorkDelay = WORK_DELAY - this.getWorkers().size(); - } else { - this.maxWorkDelay = WORK_DELAY; - } - } - - public void recalculateEnergyUsage() { - double newIdleDrain = 64; - final int allPatterns = this.getPatternBuses().stream().mapToInt(EFabricatorPatternBus::getValidPatterns).sum(); - newIdleDrain += allPatterns; - if (this.idleDrain != newIdleDrain) { - this.idleDrain = newIdleDrain; - if (this.channel != null) { - this.channel.getProxy().setIdlePowerUsage(idleDrain); - } - } - } - - public boolean insertPattern(final ItemStack patternStack) { - for (final EFabricatorPatternBus patternBus : getPatternBuses()) { - AppEngInternalInventory patternInv = patternBus.getPatterns(); - for (int i = 0; i < patternInv.getSlots(); i++) { - if (patternInv.getStackInSlot(i).isEmpty()) { - patternInv.setStackInSlot(i, ItemUtils.copyStackWithSize(patternStack, 1)); - return true; - } - } - } - - return false; - } - - public boolean offerWork(EFabricatorWorker.CraftWork work) { - boolean success = false; - for (EFabricatorWorker worker : getWorkers()) { - if (!worker.isFull()) { - var i = worker.getRemainingSpace(); - worker.offerWork(work.split(i)); - success = true; - if (work.getSize() < 1) { - break; - } - } - } - if (success && activeCooling && !speedupApplied) { - convertOverflowParallelismToWorkDelay(parallelism); - } - return success; - } - - public boolean isQueueFull() { - for (final EFabricatorWorker worker : getWorkers()) { - if (!worker.isFull()) { - return false; - } - } - return true; - } - - public boolean hasWork() { - for (EFabricatorWorker eFabricatorWorker : getWorkers()) { - if (eFabricatorWorker.hasWork()) { - return true; - } - } - return false; - } - - public synchronized void updateGUIDataPacket() { - guiDataDirty = true; - } - - public PktEFabricatorGUIData getGuiDataPacket() { - if (guiDataDirty || guiDataPacket == null) { - this.guiDataPacket = new PktEFabricatorGUIData(this); - this.guiDataDirty = false; - } - return guiDataPacket; - } - - public double getEnergyConsumePerTick() { - return idleDrain; - } - - public Levels getLevel() { - if (parentController == L4) { - return Levels.L4; - } - if (parentController == L6) { - return Levels.L6; - } - if (parentController == L9) { - return Levels.L9; - } - NovaEngineeringCore.log.warn("Invalid EFabricator controller level: {}", parentController); - return Levels.L4; - } - - public List getWorkers() { - return parts.getParts(EFabricatorWorker.class); - } - - public List getPatternBuses() { - return parts.getParts(EFabricatorPatternBus.class); - } - - public List getParallelProcs() { - return parts.getParts(EFabricatorParallelProc.class); - } - - public int getAvailableParallelism() { - return Math.max(0, parallelism - consumedParallelism); - } - - public EFabricatorController setOverclocked(final boolean overclocked) { - this.overclocked = overclocked; - updateParallelism(); - updateGUIDataPacket(); - return this; - } - - public EFabricatorController setActiveCooling(final boolean activeCooling) { - this.activeCooling = activeCooling; - updateParallelism(); - updateWorkDelay(); - updateGUIDataPacket(); - return this; - } - - public int getEnergyStored() { - return getWorkers().stream().mapToInt(EFabricatorWorker::getEnergyCache).sum(); - } - - public void consumeCoolant(final int amount) { - coolantCache -= amount; - } - - public int getCoolantInputCap() { - int total = 0; - for (final IFluidHandler handler : coolantInputHandlers) { - for (final IFluidTankProperties property : handler.getTankProperties()) { - total += Math.min(property.getCapacity(), Integer.MAX_VALUE - total); - if (total == Integer.MAX_VALUE) { - return Integer.MAX_VALUE; - } - } - } - return total; - } - - public int getCoolantInputFluids() { - int total = 0; - for (final IFluidHandler handler : coolantInputHandlers) { - for (final IFluidTankProperties property : handler.getTankProperties()) { - FluidStack contents = property.getContents(); - if (contents == null || contents.amount == 0) { - continue; - } - if (MachineCoolants.INSTANCE.getCoolant(contents.getFluid()) != null) { - total += Math.min(contents.amount, Integer.MAX_VALUE - total); - if (total == Integer.MAX_VALUE) { - return Integer.MAX_VALUE; - } - } - } - } - return total; - } - - public int getCoolantOutputCap() { - int total = 0; - for (final IFluidHandler handler : coolantOutputHandlers) { - for (final IFluidTankProperties property : handler.getTankProperties()) { - total += Math.min(property.getCapacity(), Integer.MAX_VALUE - total); - if (total == Integer.MAX_VALUE) { - return Integer.MAX_VALUE; - } - } - } - return total; - } - - public int getCoolantOutputFluids() { - int total = 0; - for (final IFluidHandler handler : coolantOutputHandlers) { - for (final IFluidTankProperties property : handler.getTankProperties()) { - FluidStack contents = property.getContents(); - if (contents == null || contents.amount == 0) { - continue; - } - total += Math.min(contents.amount, Integer.MAX_VALUE - total); - if (total == Integer.MAX_VALUE) { - return Integer.MAX_VALUE; - } - } - } - return total; - } - - @Override - protected Class getControllerBlock() { - return BlockEFabricatorController.class; - } - - @Override - public void validate() { - if (!FMLCommonHandler.instance().getEffectiveSide().isClient()) { - return; - } - - ClientProxy.clientScheduler.addRunnable(() -> { - BlockModelHider.hideOrShowBlocks(HIDE_POS_LIST, this); - notifyStructureFormedState(isStructureFormed()); - }, 0); - } - - @Override - public void invalidate() { - super.invalidate(); - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { - BlockModelHider.hideOrShowBlocks(HIDE_POS_LIST, this); - } - } - - @Override - public void onLoad() { - super.onLoad(); - if (!FMLCommonHandler.instance().getEffectiveSide().isClient()) { - return; - } - ClientProxy.clientScheduler.addRunnable(() -> { - BlockModelHider.hideOrShowBlocks(HIDE_POS_LIST, this); - notifyStructureFormedState(isStructureFormed()); - }, 0); - } - - @Override - public void readCustomNBT(final NBTTagCompound compound) { - boolean prevLoaded = loaded; - loaded = false; - - super.readCustomNBT(compound); - totalCrafted = compound.getLong("totalCrafted"); - overclocked = compound.getBoolean("overclock"); - activeCooling = compound.getBoolean("activeCooling"); - coolantCache = compound.getInteger("coolantCache"); - - outputBuffer = new ItemList(); - NBTTagList list = compound.getTagList("outputBuffer", Constants.NBT.TAG_COMPOUND); - IntStream.range(0, list.tagCount()) - .mapToObj(i -> itemChannel.createStack(ItemStackUtils.readNBTOversize(list.getCompoundTagAt(i)))) - .forEach(outputBuffer::add); - - loaded = prevLoaded; - - if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { - ClientProxy.clientScheduler.addRunnable(() -> { - BlockModelHider.hideOrShowBlocks(HIDE_POS_LIST, this); - notifyStructureFormedState(isStructureFormed()); - }, 0); - } - } - - @Override - public void writeCustomNBT(final NBTTagCompound compound) { - super.writeCustomNBT(compound); - compound.setLong("totalCrafted", totalCrafted); - compound.setBoolean("overclock", overclocked); - compound.setBoolean("activeCooling", activeCooling); - compound.setInteger("coolantCache", coolantCache); - - NBTTagList list = new NBTTagList(); - synchronized (outputBuffer) { - for (final IAEItemStack stack : outputBuffer) { - list.appendTag(ItemStackUtils.writeNBTOversize(stack.getCachedItemStack(stack.getStackSize()))); - } - } - compound.setTag("outputBuffer", list); - } - - @Override - protected void readMachineNBT(final NBTTagCompound compound) { - super.readMachineNBT(compound); - if (compound.hasKey("parentMachine")) { - ResourceLocation rl = new ResourceLocation(compound.getString("parentMachine")); - parentMachine = MachineRegistry.getRegistry().getMachine(rl); - if (parentMachine != null) { - this.parentController = BlockEFabricatorController.REGISTRY.get(new ResourceLocation(NovaEngineeringCore.MOD_ID, parentMachine.getRegistryName().getPath())); - } else { - ModularMachinery.log.info("Couldn't find machine named " + rl + " for controller at " + getPos()); - } - } - } - -} diff --git a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorController.kt b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorController.kt new file mode 100644 index 00000000..229234e4 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorController.kt @@ -0,0 +1,642 @@ +package github.kasuminova.novaeng.common.tile.ecotech.efabricator + +import appeng.api.AEApi +import appeng.api.config.Actionable +import appeng.api.config.PowerMultiplier +import appeng.api.networking.energy.IEnergyGrid +import appeng.api.storage.channels.IItemStorageChannel +import appeng.api.storage.data.IAEItemStack +import appeng.api.storage.data.IItemList +import appeng.me.GridAccessException +import appeng.util.Platform +import appeng.util.item.ItemList +import github.kasuminova.mmce.client.util.ItemStackUtils +import github.kasuminova.novaeng.NovaEngineeringCore +import github.kasuminova.novaeng.client.util.BlockModelHider +import github.kasuminova.novaeng.common.block.ecotech.efabricator.BlockEFabricatorController +import github.kasuminova.novaeng.common.block.ecotech.efabricator.prop.Levels +import github.kasuminova.novaeng.common.network.PktEFabricatorGUIData +import github.kasuminova.novaeng.common.tile.ecotech.EPartController +import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorWorker.CraftWork +import github.kasuminova.novaeng.common.util.Functions +import github.kasuminova.novaeng.common.util.MachineCoolants +import hellfirepvp.modularmachinery.ModularMachinery +import hellfirepvp.modularmachinery.client.ClientProxy +import hellfirepvp.modularmachinery.common.crafting.helper.ProcessingComponent +import hellfirepvp.modularmachinery.common.machine.IOType +import hellfirepvp.modularmachinery.common.machine.MachineRegistry +import hellfirepvp.modularmachinery.common.util.ItemUtils +import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import java.util.function.Consumer +import java.util.function.IntFunction +import java.util.stream.Collectors +import java.util.stream.IntStream +import java.util.stream.Stream +import net.minecraft.block.Block +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.nbt.NBTTagList +import net.minecraft.util.ResourceLocation +import net.minecraft.util.math.BlockPos +import net.minecraftforge.common.util.Constants +import net.minecraftforge.fluids.FluidStack +import net.minecraftforge.fluids.capability.IFluidHandler +import net.minecraftforge.fml.common.FMLCommonHandler +import kotlin.concurrent.Volatile +import kotlin.math.max +import kotlin.math.min +import kotlin.math.roundToInt +import kotlin.math.roundToLong + +@Suppress("unused") +open class EFabricatorController() : EPartController() { + + companion object { + const val MAX_COOLANT_CACHE: Int = 100000 + const val WORK_DELAY: Int = 20 + + val HIDE_POS_LIST: MutableList = Functions.asList( // Center + BlockPos(0, 1, 0), + BlockPos(0, -1, 0), + + BlockPos(0, 1, 1), + BlockPos(0, 0, 1), + BlockPos(0, -1, 1), // Left + + BlockPos(1, 1, 0), + BlockPos(1, 0, 0), + BlockPos(1, -1, 0), + + BlockPos(1, 1, 1), + BlockPos(1, 0, 1), + BlockPos(1, -1, 1), // Right + + BlockPos(-1, 1, 0), + BlockPos(-1, 0, 0), + BlockPos(-1, -1, 0), + + BlockPos(-1, 1, 1), + BlockPos(-1, 0, 1), + BlockPos(-1, -1, 1) + ) + } + + val coolantInputHandlers = ObjectArrayList() + val coolantOutputHandlers = ObjectArrayList() + + val itemChannel = AEApi.instance().storage() + .getStorageChannel(IItemStorageChannel::class.java) + + var outputBuffer: IItemList = ItemList() + + var parentController: BlockEFabricatorController? = null + var energyConsumePerTick: Double = 64.0 + + var channel: EFabricatorMEChannel? = null + + var length = 0 + + var workDelay = WORK_DELAY + var maxWorkDelay = WORK_DELAY + + var parallelism = 0 + var consumedParallelism = 0 + + var coolantCache = 0 + + var totalCrafted: Long = 0 + + var speedupApplied = false + + var overclocked = false + set(value) { + field = value + updateParallelism() + updateGUIDataPacket() + } + + var activeCooling = false + set(value) { + field = value + updateParallelism() + updateWorkDelay() + updateGUIDataPacket() + } + + var guiDataPacket: PktEFabricatorGUIData? = null + get() { + if (guiDataDirty || field == null) { + field = PktEFabricatorGUIData(this) + this.guiDataDirty = false + } + return field + } + + @Volatile + var guiDataDirty = false + + constructor(machineRegistryName: ResourceLocation) : this() { + this.parentMachine = MachineRegistry.getRegistry().getMachine(machineRegistryName) + this.parentController = BlockEFabricatorController.REGISTRY[ResourceLocation( + NovaEngineeringCore.MOD_ID, + machineRegistryName.getPath() + )] + } + + init { + this.workMode = WorkMode.SEMI_SYNC + } + + override fun onSyncTick(): Boolean { + if (channel == null || !channel!!.proxy.isActive) { + this.tickExecutor = null + return false + } + + workDelay-- + if (workDelay > 0) { + this.tickExecutor = null + return false + } + workDelay = maxWorkDelay + speedupApplied = false + clearOutputBuffer() + supplyWorkerPower() + supplyCoolantCache() + return true + } + + override fun onAsyncTick() { + updateGUIDataPacket() + + val prevTotalCrafted = totalCrafted + val workers = this.workers + workers.forEach(Consumer { worker: EFabricatorWorker? -> worker!!.updateStatus(false) }) + for (worker in workers) { + if (worker.hasWork()) { + val worked = worker.doWork() + totalCrafted += worked.toLong() + consumedParallelism += if (worked <= 1) 0 else worked + } + } + if (activeCooling && hasWork()) { + convertOverflowParallelismToWorkDelay(parallelism - consumedParallelism) + } + consumedParallelism = 0 + + if (prevTotalCrafted != totalCrafted) { + markNoUpdateSync() + } + } + + fun supplyCoolantCache() { + if (coolantCache >= MAX_COOLANT_CACHE) { + return + } + + // 写了一坨大的! + for (inputHandler in coolantInputHandlers) { + for (property in inputHandler.getTankProperties()) { + val contents = property.getContents() + if (contents == null || contents.amount == 0) { + continue + } + + val coolant = MachineCoolants.INSTANCE.getCoolant(contents.fluid) ?: continue + + for (outputHandler in coolantOutputHandlers) { + val maxCanConsume = coolant.maxCanConsume(inputHandler, outputHandler) + if (maxCanConsume <= 0) { + continue + } + + val required: Int = MAX_COOLANT_CACHE - coolantCache + var mul = required / coolant.coolantUnit + if (mul * coolant.coolantUnit < required) { + mul++ + } + mul = min(mul, maxCanConsume) + + if (mul > 0) { + val input = coolant.input + inputHandler.drain(FluidStack(input, mul * input.amount), true) + val output = coolant.output + if (output != null) { + outputHandler.fill(FluidStack(output, mul * output.amount), true) + } + coolantCache += mul * coolant.coolantUnit + if (coolantCache >= MAX_COOLANT_CACHE) { + return + } + } + } + } + } + } + + fun supplyWorkerPower() { + val energy: IEnergyGrid + try { + energy = channel!!.proxy.energy + } catch (ignored: GridAccessException) { + return + } + + for (worker in this.workers) { + if (worker.energyCache < worker.getMaxEnergyCache()) { + worker.supplyEnergy( + energy.extractAEPower( + (worker.getMaxEnergyCache() - worker.energyCache).toDouble(), + Actionable.MODULATE, + PowerMultiplier.CONFIG + ).toInt() + ) + } + } + } + + fun clearOutputBuffer() { + try { + val proxy = this.channel!!.proxy + val inv = proxy.storage.getInventory(itemChannel) + for (stack in outputBuffer) { + val notInserted = Platform.poweredInsert( + proxy.energy, + inv, + stack.copy(), + this.channel!!.source + ) + if (notInserted != null) { + stack.stackSize = notInserted.stackSize + } else { + stack.stackSize = 0 + } + } + } catch (ignored: GridAccessException) { + } + } + + override fun updateComponents() { + super.updateComponents() + val workers = getDynamicPattern("workers") + this.length = workers?.size ?: 0 + this.foundComponents.values.forEach(Consumer { component: ProcessingComponent<*>? -> + val handler = component!!.providedComponent() + if (handler is IFluidHandler) { + when (component.getComponent().ioType) { + IOType.INPUT -> coolantInputHandlers.add(handler) + IOType.OUTPUT -> coolantOutputHandlers.add(handler) + } + } + }) + updateParallelism() + updateWorkDelay() + } + + override fun onAddPart(part: EFabricatorPart?) { + if (part is EFabricatorMEChannel) { + this.channel = part + } + } + + override fun clearParts() { + super.clearParts() + this.coolantInputHandlers.clear() + this.coolantOutputHandlers.clear() + this.channel = null + this.length = 0 + } + + fun updateParallelism() { + val parallelism = doubleArrayOf(0.0) + val modifierMap: MutableMap> = + this.parallelProcs.stream() + .flatMap { proc: EFabricatorParallelProc? -> + if (overclocked) Stream.concat( + proc!!.modifiers.stream(), + proc.overclockModifiers.stream() + ) else proc!!.modifiers.stream() + } // 超频额外添加超频修正器 + .filter { modifier: EFabricatorParallelProc.Modifier -> modifier.isBuff || !activeCooling } // 主动冷却移除超频的负面效果。 + .collect( + Collectors.groupingBy( + EFabricatorParallelProc.Modifier::type, + { + Object2ObjectAVLTreeMap>( + Comparator.comparingInt(EFabricatorParallelProc.Type::priority) + ) + }, + Collectors.toCollection { ObjectArrayList() } + ) + ) + + modifierMap.values.stream() + .flatMap { obj: MutableList -> obj.stream() } + .filter { obj: EFabricatorParallelProc.Modifier -> obj.isBuff } + .forEach { modifier: EFabricatorParallelProc.Modifier -> + parallelism[0] = modifier.apply(parallelism[0]) + } + modifierMap.values.stream() + .flatMap { obj: MutableList -> obj.stream() } + .filter(EFabricatorParallelProc.Modifier::debuff) + .forEach { modifier: EFabricatorParallelProc.Modifier -> + parallelism[0] = modifier.apply(parallelism[0]) + } + + this.parallelism = parallelism[0].roundToLong().toInt() + } + + @Synchronized + fun convertOverflowParallelismToWorkDelay(overflow: Int) { + if (overflow <= 0 || speedupApplied) { + return + } + val ratio = parallelism.toFloat() / overflow + var speedUp = min((ratio / 0.05f).roundToInt(), maxWorkDelay - 1) + + val coolantUsage = parallelism * 0.04 + val maxCanConsume = (coolantCache / coolantUsage).toInt() + speedUp = min(speedUp, maxCanConsume) + coolantCache -= (speedUp * coolantUsage).roundToLong().toInt() + + this.workDelay = maxWorkDelay - speedUp + this.speedupApplied = true + } + + fun updateWorkDelay() { + if (activeCooling) { + this.maxWorkDelay = WORK_DELAY - this.workers.size + } else { + this.maxWorkDelay = WORK_DELAY + } + } + + fun recalculateEnergyUsage() { + var newIdleDrain = 64.0 + val allPatterns = + this.patternBuses.stream().mapToInt { obj: EFabricatorPatternBus? -> obj!!.validPatterns }.sum() + newIdleDrain += allPatterns.toDouble() + if (this.energyConsumePerTick != newIdleDrain) { + this.energyConsumePerTick = newIdleDrain + if (this.channel != null) { + this.channel!!.proxy.idlePowerUsage = this.energyConsumePerTick + } + } + } + + fun insertPattern(patternStack: ItemStack): Boolean { + for (patternBus in this.patternBuses) { + val patternInv = patternBus.patterns + for (i in 0.. + get() = parts.getParts(EFabricatorWorker::class.java) + + val patternBuses: List + get() = parts.getParts(EFabricatorPatternBus::class.java) + + val parallelProcs: List + get() = parts.getParts(EFabricatorParallelProc::class.java) + + val availableParallelism: Int + get() = max(0, parallelism - consumedParallelism) + + val energyStored: Int + get() = this.workers.stream().mapToInt { obj: EFabricatorWorker -> obj.energyCache }.sum() + + fun consumeCoolant(amount: Int) { + coolantCache -= amount + } + + val coolantInputCap: Int + get() { + var total = 0 + for (handler in coolantInputHandlers) { + for (property in handler.getTankProperties()) { + total += min(property.getCapacity(), Int.MAX_VALUE - total) + if (total == Int.MAX_VALUE) { + return Int.MAX_VALUE + } + } + } + return total + } + + val coolantInputFluids: Int + get() { + var total = 0 + for (handler in coolantInputHandlers) { + for (property in handler.getTankProperties()) { + val contents = property.getContents() + if (contents == null || contents.amount == 0) { + continue + } + if (MachineCoolants.INSTANCE.getCoolant(contents.fluid) != null) { + total += min(contents.amount, Int.MAX_VALUE - total) + if (total == Int.MAX_VALUE) { + return Int.MAX_VALUE + } + } + } + } + return total + } + + val coolantOutputCap: Int + get() { + var total = 0 + for (handler in coolantOutputHandlers) { + for (property in handler.getTankProperties()) { + total += min(property.getCapacity(), Int.MAX_VALUE - total) + if (total == Int.MAX_VALUE) { + return Int.MAX_VALUE + } + } + } + return total + } + + val coolantOutputFluids: Int + get() { + var total = 0 + for (handler in coolantOutputHandlers) { + for (property in handler.getTankProperties()) { + val contents = property.getContents() + if (contents == null || contents.amount == 0) { + continue + } + total += min(contents.amount, Int.MAX_VALUE - total) + if (total == Int.MAX_VALUE) { + return Int.MAX_VALUE + } + } + } + return total + } + + override fun getControllerBlock(): Class { + return BlockEFabricatorController::class.java + } + + override fun validate() { + if (!FMLCommonHandler.instance().getEffectiveSide().isClient) { + return + } + + ClientProxy.clientScheduler.addRunnable({ + BlockModelHider.hideOrShowBlocks(HIDE_POS_LIST, this) + notifyStructureFormedState(isStructureFormed) + }, 0) + } + + override fun invalidate() { + super.invalidate() + if (FMLCommonHandler.instance().getEffectiveSide().isClient) { + BlockModelHider.hideOrShowBlocks(HIDE_POS_LIST, this) + } + } + + override fun onLoad() { + super.onLoad() + if (!FMLCommonHandler.instance().getEffectiveSide().isClient) { + return + } + ClientProxy.clientScheduler.addRunnable({ + BlockModelHider.hideOrShowBlocks(HIDE_POS_LIST, this) + notifyStructureFormedState(isStructureFormed) + }, 0) + } + + override fun readCustomNBT(compound: NBTTagCompound) { + val prevLoaded = loaded + loaded = false + + super.readCustomNBT(compound) + totalCrafted = compound.getLong("totalCrafted") + overclocked = compound.getBoolean("overclock") + activeCooling = compound.getBoolean("activeCooling") + coolantCache = compound.getInteger("coolantCache") + + outputBuffer = ItemList() + val list = compound.getTagList("outputBuffer", Constants.NBT.TAG_COMPOUND) + IntStream.range(0, list.tagCount()) + .mapToObj(IntFunction { i: Int -> + itemChannel.createStack( + ItemStackUtils.readNBTOversize( + list.getCompoundTagAt( + i + ) + ) + ) + }) + .forEach { t: IAEItemStack? -> outputBuffer.add(t) } + + loaded = prevLoaded + + if (FMLCommonHandler.instance().getEffectiveSide().isClient) { + ClientProxy.clientScheduler.addRunnable({ + BlockModelHider.hideOrShowBlocks(HIDE_POS_LIST, this) + notifyStructureFormedState(isStructureFormed) + }, 0) + } + } + + override fun writeCustomNBT(compound: NBTTagCompound) { + super.writeCustomNBT(compound) + compound.setLong("totalCrafted", totalCrafted) + compound.setBoolean("overclock", overclocked) + compound.setBoolean("activeCooling", activeCooling) + compound.setInteger("coolantCache", coolantCache) + + val list = NBTTagList() + synchronized(outputBuffer) { + for (stack in outputBuffer) { + list.appendTag(ItemStackUtils.writeNBTOversize(stack.getCachedItemStack(stack.stackSize))) + } + } + compound.setTag("outputBuffer", list) + } + + override fun readMachineNBT(compound: NBTTagCompound) { + super.readMachineNBT(compound) + if (compound.hasKey("parentMachine")) { + val rl = ResourceLocation(compound.getString("parentMachine")) + parentMachine = MachineRegistry.getRegistry().getMachine(rl) + if (parentMachine != null) { + this.parentController = BlockEFabricatorController.REGISTRY[ResourceLocation( + NovaEngineeringCore.MOD_ID, + parentMachine.getRegistryName().getPath() + )] + } else { + ModularMachinery.log.info("Couldn't find machine named " + rl + " for controller at " + getPos()) + } + } + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorMEChannel.java b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorMEChannel.java deleted file mode 100644 index bae1218b..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorMEChannel.java +++ /dev/null @@ -1,281 +0,0 @@ -package github.kasuminova.novaeng.common.tile.ecotech.efabricator; - -import appeng.api.networking.GridFlags; -import appeng.api.networking.IGridNode; -import appeng.api.networking.crafting.ICraftingPatternDetails; -import appeng.api.networking.crafting.ICraftingProvider; -import appeng.api.networking.crafting.ICraftingProviderHelper; -import appeng.api.networking.events.MENetworkChannelsChanged; -import appeng.api.networking.events.MENetworkCraftingPatternChange; -import appeng.api.networking.events.MENetworkEventSubscribe; -import appeng.api.networking.events.MENetworkPowerStatusChange; -import appeng.api.networking.security.IActionHost; -import appeng.api.networking.security.IActionSource; -import appeng.api.storage.data.IAEItemStack; -import appeng.api.util.AECableType; -import appeng.api.util.AEPartLocation; -import appeng.api.util.DimensionalCoord; -import appeng.me.GridAccessException; -import appeng.me.helpers.AENetworkProxy; -import appeng.me.helpers.IGridProxyable; -import appeng.me.helpers.MachineSource; -import com.glodblock.github.common.item.ItemFluidPacket; -import com.glodblock.github.common.item.fake.FakeItemRegister; -import com.glodblock.github.util.FluidCraftingPatternDetails; -import github.kasuminova.mmce.common.util.PatternItemFilter; -import github.kasuminova.novaeng.common.block.ecotech.efabricator.BlockEFabricatorMEChannel; -import hellfirepvp.modularmachinery.ModularMachinery; -import lombok.Getter; -import net.minecraft.inventory.InventoryCrafting; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.fluids.FluidStack; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.List; - -public class EFabricatorMEChannel extends EFabricatorPart implements ICraftingProvider, IActionHost, IGridProxyable { - - protected final AENetworkProxy proxy = new AENetworkProxy(this, "channel", getVisualItemStack(), true); - @Getter - protected final IActionSource source = new MachineSource(this); - - private boolean wasActive = false; - - public EFabricatorMEChannel() { - this.proxy.setIdlePowerUsage(1.0D); - this.proxy.setFlags(GridFlags.REQUIRE_CHANNEL, GridFlags.DENSE_CAPACITY); - } - - private static ItemStack getContainerItem(ItemStack stackInSlot) { - if (stackInSlot == null) { - return ItemStack.EMPTY; - } else { - Item i = stackInSlot.getItem(); - if (i != null && i.hasContainerItem(stackInSlot)) { - ItemStack ci = i.getContainerItem(stackInSlot); - if (!ci.isEmpty() && ci.isItemStackDamageable() && ci.getItemDamage() == ci.getMaxDamage()) { - ci = ItemStack.EMPTY; - } - - ci.setCount(stackInSlot.getCount()); - return ci; - } else if (!stackInSlot.isEmpty()) { - stackInSlot.setCount(0); - return stackInSlot; - } else return ItemStack.EMPTY; - } - } - - public ItemStack getVisualItemStack() { - EFabricatorController controller = getController(); - return new ItemStack(Item.getItemFromBlock(controller == null ? BlockEFabricatorMEChannel.INSTANCE : controller.getParentController()), 1, 0); - } - - @MENetworkEventSubscribe - public void stateChange(final MENetworkPowerStatusChange c) { - postPatternChangeEvent(); - } - - @MENetworkEventSubscribe - public void stateChange(final MENetworkChannelsChanged c) { - postPatternChangeEvent(); - } - - // Crafting Provider - - protected void postPatternChangeEvent() { - final boolean currentActive = this.proxy.isActive(); - if (this.wasActive != currentActive) { - this.wasActive = currentActive; - try { - this.proxy.getGrid().postEvent(new MENetworkCraftingPatternChange(this, proxy.getNode())); - } catch (final GridAccessException ignored) { - } - } - } - - @Override - public void provideCrafting(final ICraftingProviderHelper craftingTracker) { - EFabricatorController controller = getController(); - if (controller == null) { - return; - } - - List patternBuses = controller.getPatternBuses(); - patternBuses.stream() - .flatMap(patternBus -> patternBus.getDetails().stream()) - .filter(details -> details.isCraftable() || details instanceof FluidCraftingPatternDetails) - .forEach(details -> craftingTracker.addCraftingOption(this, details)); - } - - @Override - public boolean pushPattern(final ICraftingPatternDetails pattern, final InventoryCrafting table) { - if (isBusy()) { - return false; - } - - if (!pattern.isCraftable()) { - if (pattern instanceof FluidCraftingPatternDetails f) { - return pushFluidPattern(f, table); - } - return false; - } - - ItemStack output = pattern.getOutput(table, this.getWorld()); - if (output.isEmpty()) { - return false; - } - - ItemStack[] remaining = new ItemStack[9]; - int size = 0; - for (int i = 0; i < Math.min(table.getSizeInventory(), 9); ++i) { - var item = table.getStackInSlot(i); - if (item.isEmpty()) { - remaining[i] = ItemStack.EMPTY; - } else { - if (size == 0) { - size = item.getCount(); - } - remaining[i] = getContainerItem(item); - } - } - - output.setCount(output.getCount() * size); - - return partController.offerWork(new EFabricatorWorker.CraftWork(remaining, output, size)); - } - - protected boolean pushFluidPattern(final FluidCraftingPatternDetails pattern, final InventoryCrafting table) { - IAEItemStack[] outputs = pattern.getOutputs(); - ItemStack output = outputs[0] != null ? outputs[0].getCachedItemStack(outputs[0].getStackSize()) : ItemStack.EMPTY; - - if (output.isEmpty()) return false; - - ItemStack[] remaining = new ItemStack[9]; - int size = 0; - for (int i = 0; i < Math.min(table.getSizeInventory(), 9); ++i) { - var item = table.getStackInSlot(i); - if (item.isEmpty()) { - remaining[i] = ItemStack.EMPTY; - } else { - if (size == 0) { - size = item.getCount(); - if (item.getItem() instanceof ItemFluidPacket) { - var amount = ((FluidStack) FakeItemRegister.getStack(item)).amount; - var pamount = ((FluidStack) FakeItemRegister.getStack(pattern.getInputs()[i])).amount; - size = amount / pamount; - } - } - remaining[i] = getContainerItem(item); - } - } - - output.setCount(output.getCount() * size); - - return partController.offerWork(new EFabricatorWorker.CraftWork(remaining, output, size)); - } - - public boolean insertPattern(final ItemStack patternStack) { - if (!PatternItemFilter.INSTANCE.allowInsert(null, -1, patternStack)) { - return false; - } - if (partController != null) { - return partController.insertPattern(patternStack); - } - return false; - } - - @Override - public boolean isBusy() { - if (partController != null) { - return partController.isQueueFull(); - } - return true; - } - - // Misc - - @Nonnull - @Override - public IGridNode getActionableNode() { - return proxy.getNode(); - } - - @Nonnull - @Override - public AENetworkProxy getProxy() { - return proxy; - } - - @Nonnull - @Override - public DimensionalCoord getLocation() { - return new DimensionalCoord(this); - } - - @Override - public void gridChanged() { - } - - @Nullable - @Override - public IGridNode getGridNode(@Nonnull final AEPartLocation dir) { - return proxy.getNode(); - } - - @Nonnull - @Override - public AECableType getCableConnectionType(@Nonnull final AEPartLocation dir) { - return AECableType.DENSE_SMART; - } - - @Override - public void securityBreak() { - getWorld().destroyBlock(getPos(), true); - } - - @Override - public void readCustomNBT(final NBTTagCompound compound) { - super.readCustomNBT(compound); - proxy.readFromNBT(compound); - } - - @Override - public void writeCustomNBT(final NBTTagCompound compound) { - super.writeCustomNBT(compound); - proxy.writeToNBT(compound); - } - - @Override - public void onChunkUnload() { - super.onChunkUnload(); - proxy.onChunkUnload(); - } - - @Override - public void invalidate() { - super.invalidate(); - proxy.invalidate(); - } - - @Override - public void onAssembled() { - super.onAssembled(); - proxy.setVisualRepresentation(getVisualItemStack()); - ModularMachinery.EXECUTE_MANAGER.addSyncTask(() -> { - proxy.onReady(); - partController.recalculateEnergyUsage(); - }); - } - - @Override - public void onDisassembled() { - super.onDisassembled(); - proxy.setVisualRepresentation(getVisualItemStack()); - proxy.invalidate(); - } - -} diff --git a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorMEChannel.kt b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorMEChannel.kt new file mode 100644 index 00000000..e2554dae --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorMEChannel.kt @@ -0,0 +1,264 @@ +package github.kasuminova.novaeng.common.tile.ecotech.efabricator + +import appeng.api.networking.GridFlags +import appeng.api.networking.IGridNode +import appeng.api.networking.crafting.ICraftingPatternDetails +import appeng.api.networking.crafting.ICraftingProvider +import appeng.api.networking.crafting.ICraftingProviderHelper +import appeng.api.networking.events.MENetworkChannelsChanged +import appeng.api.networking.events.MENetworkCraftingPatternChange +import appeng.api.networking.events.MENetworkEventSubscribe +import appeng.api.networking.events.MENetworkPowerStatusChange +import appeng.api.networking.security.IActionHost +import appeng.api.networking.security.IActionSource +import appeng.api.util.AECableType +import appeng.api.util.AEPartLocation +import appeng.api.util.DimensionalCoord +import appeng.me.GridAccessException +import appeng.me.helpers.AENetworkProxy +import appeng.me.helpers.IGridProxyable +import appeng.me.helpers.MachineSource +import com.glodblock.github.common.item.ItemFluidPacket +import com.glodblock.github.common.item.fake.FakeItemRegister +import com.glodblock.github.util.FluidCraftingPatternDetails +import github.kasuminova.mmce.common.util.PatternItemFilter +import github.kasuminova.novaeng.common.block.ecotech.efabricator.BlockEFabricatorMEChannel +import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorWorker.CraftWork +import hellfirepvp.modularmachinery.ModularMachinery +import net.minecraft.inventory.InventoryCrafting +import net.minecraft.item.Item +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraftforge.fluids.FluidStack +import javax.annotation.Nonnull +import kotlin.math.min + +open class EFabricatorMEChannel : EFabricatorPart(), ICraftingProvider, IActionHost, IGridProxyable { + + companion object { + private fun getContainerItem(stackInSlot: ItemStack?): ItemStack { + if (stackInSlot == null) { + return ItemStack.EMPTY + } else { + val i = stackInSlot.item + if (i != null && i.hasContainerItem(stackInSlot)) { + var ci = i.getContainerItem(stackInSlot) + if (!ci.isEmpty && ci.isItemStackDamageable && ci.getItemDamage() == ci.maxDamage) { + ci = ItemStack.EMPTY + } + + ci.setCount(stackInSlot.count) + return ci + } else if (!stackInSlot.isEmpty) { + stackInSlot.setCount(0) + return stackInSlot + } else return ItemStack.EMPTY + } + } + } + + private val aEProxy: AENetworkProxy = AENetworkProxy(this, "channel", this.visualItemStack, true) + val source: IActionSource = MachineSource(this) + + private var wasActive = false + + init { + this.aEProxy.idlePowerUsage = 1.0 + this.aEProxy.setFlags(GridFlags.REQUIRE_CHANNEL, GridFlags.DENSE_CAPACITY) + } + + val visualItemStack: ItemStack + get() { + val controller: EFabricatorController? = getController() + return ItemStack( + Item.getItemFromBlock(if (controller == null) BlockEFabricatorMEChannel.INSTANCE else controller.parentController!!), + 1, + 0 + ) + } + + @MENetworkEventSubscribe + fun stateChange(c: MENetworkPowerStatusChange?) { + postPatternChangeEvent() + } + + @MENetworkEventSubscribe + fun stateChange(c: MENetworkChannelsChanged?) { + postPatternChangeEvent() + } + + // Crafting Provider + protected fun postPatternChangeEvent() { + val currentActive = this.aEProxy.isActive + if (this.wasActive != currentActive) { + this.wasActive = currentActive + try { + this.aEProxy.grid.postEvent(MENetworkCraftingPatternChange(this, aEProxy.node)) + } catch (ignored: GridAccessException) { + } + } + } + + override fun provideCrafting(craftingTracker: ICraftingProviderHelper) { + val controller: EFabricatorController = controller ?: return + + val patternBuses: List = controller.patternBuses + patternBuses.stream() + .flatMap { patternBus: EFabricatorPatternBus? -> + patternBus!!.getDetails().stream() + } + .filter { details: ICraftingPatternDetails? -> details!!.isCraftable || details is FluidCraftingPatternDetails } + .forEach { details: ICraftingPatternDetails? -> craftingTracker.addCraftingOption(this, details) } + } + + override fun pushPattern(pattern: ICraftingPatternDetails, table: InventoryCrafting): Boolean { + if (isBusy()) { + return false + } + + if (!pattern.isCraftable) { + if (pattern is FluidCraftingPatternDetails) { + return pushFluidPattern(pattern, table) + } + return false + } + + val output = pattern.getOutput(table, this.getWorld()) + if (output.isEmpty) { + return false + } + + val remaining = Array(9) { i -> ItemStack.EMPTY } + var size = 0 + for (i in 0..(9) { i -> ItemStack.EMPTY } + var size = 0 + for (i in 0..(item) as FluidStack).amount + val pamount = (FakeItemRegister.getStack(pattern.inputs[i]) as FluidStack).amount + size = amount / pamount + } + } + remaining[i] = getContainerItem(item) + } + } + + output.setCount(output.count * size) + + return partController.offerWork(CraftWork(remaining, output, size)) + } + + fun insertPattern(patternStack: ItemStack): Boolean { + if (!PatternItemFilter.INSTANCE.allowInsert(null, -1, patternStack)) { + return false + } + if (partController != null) { + return partController.insertPattern(patternStack) + } + return false + } + + override fun isBusy(): Boolean { + if (partController != null) { + return partController.isQueueFull + } + return true + } + + // Misc + @Nonnull + override fun getActionableNode(): IGridNode { + return aEProxy.node + } + + @Nonnull + override fun getProxy(): AENetworkProxy { + return aEProxy + } + + @Nonnull + override fun getLocation(): DimensionalCoord { + return DimensionalCoord(this) + } + + override fun gridChanged() { + } + + override fun getGridNode(@Nonnull dir: AEPartLocation): IGridNode? { + return aEProxy.node + } + + @Nonnull + override fun getCableConnectionType(@Nonnull dir: AEPartLocation): AECableType { + return AECableType.DENSE_SMART + } + + override fun securityBreak() { + getWorld().destroyBlock(getPos(), true) + } + + override fun readCustomNBT(compound: NBTTagCompound?) { + super.readCustomNBT(compound) + aEProxy.readFromNBT(compound) + } + + override fun writeCustomNBT(compound: NBTTagCompound?) { + super.writeCustomNBT(compound) + aEProxy.writeToNBT(compound) + } + + override fun onChunkUnload() { + super.onChunkUnload() + aEProxy.onChunkUnload() + } + + override fun invalidate() { + super.invalidate() + aEProxy.invalidate() + } + + override fun onAssembled() { + super.onAssembled() + aEProxy.setVisualRepresentation(this.visualItemStack) + ModularMachinery.EXECUTE_MANAGER.addSyncTask { + aEProxy.onReady() + partController.recalculateEnergyUsage() + } + } + + override fun onDisassembled() { + super.onDisassembled() + aEProxy.setVisualRepresentation(this.visualItemStack) + aEProxy.invalidate() + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorParallelProc.java b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorParallelProc.java deleted file mode 100644 index 05779fa5..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorParallelProc.java +++ /dev/null @@ -1,118 +0,0 @@ -package github.kasuminova.novaeng.common.tile.ecotech.efabricator; - -import com.github.bsideup.jabel.Desugar; -import github.kasuminova.novaeng.common.crafttweaker.util.NovaEngUtils; -import lombok.Getter; -import net.minecraft.client.resources.I18n; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraftforge.common.util.Constants; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import java.util.ArrayList; -import java.util.List; - -@Getter -public class EFabricatorParallelProc extends EFabricatorPart { - - protected final List modifiers = new ArrayList<>(); - protected final List overclockModifiers = new ArrayList<>(); - - public EFabricatorParallelProc() { - } - - public EFabricatorParallelProc(List modifiers, List overclockModifiers) { - this.modifiers.addAll(modifiers); - this.overclockModifiers.addAll(overclockModifiers); - } - - @Override - public void readCustomNBT(final NBTTagCompound compound) { - super.readCustomNBT(compound); - modifiers.clear(); - compound.getTagList("modifiers", Constants.NBT.TAG_COMPOUND) - .forEach(tag -> modifiers.add(Modifier.readFromNBT((NBTTagCompound) tag))); - - overclockModifiers.clear(); - compound.getTagList("overclockModifiers", Constants.NBT.TAG_COMPOUND) - .forEach(tag -> overclockModifiers.add(Modifier.readFromNBT((NBTTagCompound) tag))); - } - - @Override - public void writeCustomNBT(final NBTTagCompound compound) { - super.writeCustomNBT(compound); - NBTTagList modifiersTag = new NBTTagList(); - modifiers.forEach(modifier -> modifiersTag.appendTag(modifier.writeToNBT())); - compound.setTag("modifiers", modifiersTag); - - NBTTagList overclockModifiersTag = new NBTTagList(); - overclockModifiers.forEach(modifier -> overclockModifiersTag.appendTag(modifier.writeToNBT())); - compound.setTag("overclockModifiers", overclockModifiersTag); - } - - @Getter - public enum Type { - - ADD(0), - MULTIPLY(1); - - final int priority; - - Type(int priority) { - this.priority = priority; - } - - public double apply(final double value, final double parallelism) { - return switch (this) { - case ADD -> value + parallelism; - case MULTIPLY -> value * parallelism; - }; - } - - } - - @Desugar - public record Modifier(Type type, double value, boolean debuff) { - - public static Modifier readFromNBT(NBTTagCompound tag) { - return new Modifier(Type.values()[tag.getByte("type")], tag.getDouble("value"), tag.getBoolean("debuff")); - } - - public double apply(final double parallelism) { - return type.apply(value, parallelism); - } - - public boolean isBuff() { - return !debuff; - } - - public NBTTagCompound writeToNBT() { - NBTTagCompound tag = new NBTTagCompound(); - tag.setByte("type", (byte) type.ordinal()); - tag.setDouble("value", value); - tag.setBoolean("debuff", debuff); - return tag; - } - - @SideOnly(Side.CLIENT) - public String getDesc() { - switch (type) { - case ADD -> { - return isBuff() - ? I18n.format("novaeng.efabricator_parallel_proc.modifier.add", value) - : I18n.format("novaeng.efabricator_parallel_proc.modifier.sub", Math.abs(value)); - } - case MULTIPLY -> { - return isBuff() - ? I18n.format("novaeng.efabricator_parallel_proc.modifier.mul", - NovaEngUtils.formatDouble((1D - value) * 100, 1)) - : I18n.format("novaeng.efabricator_parallel_proc.modifier.mul.debuff", - NovaEngUtils.formatDouble(Math.abs(1D - value) * 100, 1)); - } - } - return ""; - } - } - -} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorParallelProc.kt b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorParallelProc.kt new file mode 100644 index 00000000..b4639581 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorParallelProc.kt @@ -0,0 +1,121 @@ +package github.kasuminova.novaeng.common.tile.ecotech.efabricator + +import github.kasuminova.novaeng.common.crafttweaker.util.NovaEngUtils +import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorParallelProc.Type.ADD +import github.kasuminova.novaeng.common.tile.ecotech.efabricator.EFabricatorParallelProc.Type.MULTIPLY +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import java.util.function.Consumer +import net.minecraft.client.resources.I18n +import net.minecraft.nbt.NBTBase +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.nbt.NBTTagList +import net.minecraftforge.common.util.Constants +import net.minecraftforge.fml.relauncher.Side +import net.minecraftforge.fml.relauncher.SideOnly +import kotlin.math.abs + +open class EFabricatorParallelProc : EFabricatorPart { + val modifiers: MutableList = ObjectArrayList() + val overclockModifiers: MutableList = ObjectArrayList() + + constructor() + + constructor(modifiers: MutableList, overclockModifiers: MutableList) { + this.modifiers.addAll(modifiers) + this.overclockModifiers.addAll(overclockModifiers) + } + + override fun readCustomNBT(compound: NBTTagCompound) { + super.readCustomNBT(compound) + modifiers.clear() + compound.getTagList("modifiers", Constants.NBT.TAG_COMPOUND) + .forEach(Consumer { tag: NBTBase? -> modifiers.add(Modifier.readFromNBT((tag as NBTTagCompound?)!!)) }) + + overclockModifiers.clear() + compound.getTagList("overclockModifiers", Constants.NBT.TAG_COMPOUND) + .forEach(Consumer { tag: NBTBase? -> overclockModifiers.add(Modifier.readFromNBT((tag as NBTTagCompound?)!!)) }) + } + + override fun writeCustomNBT(compound: NBTTagCompound) { + super.writeCustomNBT(compound) + val modifiersTag = NBTTagList() + modifiers.forEach(Consumer { modifier: Modifier? -> modifiersTag.appendTag(modifier!!.writeToNBT()) }) + compound.setTag("modifiers", modifiersTag) + + val overclockModifiersTag = NBTTagList() + overclockModifiers.forEach(Consumer { modifier: Modifier? -> overclockModifiersTag.appendTag(modifier!!.writeToNBT()) }) + compound.setTag("overclockModifiers", overclockModifiersTag) + } + + enum class Type(val priority: Int) { + ADD(0), + MULTIPLY(1); + + fun apply(value: Double, parallelism: Double): Double { + return when (this) { + ADD -> value + parallelism + MULTIPLY -> value * parallelism + } + } + } + + data class Modifier(val type: Type, val value: Double, val debuff: Boolean) { + + companion object { + fun readFromNBT(tag: NBTTagCompound): Modifier { + return Modifier( + Type.entries[tag.getByte("type").toInt()], + tag.getDouble("value"), + tag.getBoolean("debuff") + ) + } + } + + fun apply(parallelism: Double): Double { + return type.apply(value, parallelism) + } + + val isBuff: Boolean + get() = !debuff + + fun writeToNBT(): NBTTagCompound { + val tag = NBTTagCompound() + tag.setByte("type", type.ordinal.toByte()) + tag.setDouble("value", value) + tag.setBoolean("debuff", debuff) + return tag + } + + @get:SideOnly(Side.CLIENT) + val desc: String + get() { + when (type) { + ADD -> { + return if (this.isBuff) + I18n.format( + "novaeng.efabricator_parallel_proc.modifier.add", + value + ) + else + I18n.format( + "novaeng.efabricator_parallel_proc.modifier.sub", + abs(value) + ) + } + + MULTIPLY -> { + return if (this.isBuff) + I18n.format( + "novaeng.efabricator_parallel_proc.modifier.mul", + NovaEngUtils.formatDouble((1.0 - value) * 100, 1) + ) + else + I18n.format( + "novaeng.efabricator_parallel_proc.modifier.mul.debuff", + NovaEngUtils.formatDouble(abs(1.0 - value) * 100, 1) + ) + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorPatternBus.java b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorPatternBus.java deleted file mode 100644 index 2598069c..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorPatternBus.java +++ /dev/null @@ -1,171 +0,0 @@ -package github.kasuminova.novaeng.common.tile.ecotech.efabricator; - -import appeng.api.implementations.ICraftingPatternItem; -import appeng.api.networking.crafting.ICraftingPatternDetails; -import appeng.api.networking.events.MENetworkCraftingPatternChange; -import appeng.me.GridAccessException; -import appeng.tile.inventory.AppEngInternalInventory; -import appeng.util.inv.IAEAppEngInventory; -import appeng.util.inv.InvOperation; -import com.glodblock.github.util.FluidCraftingPatternDetails; -import github.kasuminova.mmce.common.util.PatternItemFilter; -import github.kasuminova.novaeng.NovaEngineeringCore; -import github.kasuminova.novaeng.common.container.ContainerEFabricatorPatternSearch; -import github.kasuminova.novaeng.common.container.data.EFabricatorPatternData; -import github.kasuminova.novaeng.common.network.PktEFabricatorPatternSearchGUIUpdate; -import hellfirepvp.modularmachinery.ModularMachinery; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import lombok.Getter; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fml.common.FMLCommonHandler; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -public class EFabricatorPatternBus extends EFabricatorPart implements IAEAppEngInventory { - - public static final int PATTERN_SLOTS = 12 * 6; - - @Getter - protected final AppEngInternalInventory patterns = new AppEngInternalInventory(this, PATTERN_SLOTS, 1, PatternItemFilter.INSTANCE); - protected final List details = new ObjectArrayList<>(PATTERN_SLOTS); - - public EFabricatorPatternBus() { - // Initialize details... - IntStream.range(0, PATTERN_SLOTS).mapToObj(i -> null).forEach(details::add); - } - - protected void refreshPatterns() { - for (int i = 0; i < PATTERN_SLOTS; i++) { - refreshPattern(i); - } - notifyPatternChanged(); - } - - protected void refreshPattern(final int slot) { - details.set(slot, null); - - ItemStack pattern = patterns.getStackInSlot(slot); - Item item = pattern.getItem(); - if (pattern.isEmpty() || !(item instanceof ICraftingPatternItem patternItem)) { - return; - } - - ICraftingPatternDetails detail = patternItem.getPatternForItem(pattern, getWorld()); - if (detail != null && (detail.isCraftable() || detail instanceof FluidCraftingPatternDetails)) { - details.set(slot, detail); - } - } - - public List getDetails() { - return details.stream() - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - public int getValidPatterns() { - return (int) details.stream().filter(Objects::nonNull).count(); - } - - @Override - public void saveChanges() { - markNoUpdateSync(); - } - - @Override - public void onChangeInventory(final IItemHandler inv, final int slot, final InvOperation mc, final ItemStack removedStack, final ItemStack newStack) { - refreshPattern(slot); - notifyPatternChanged(); - sendPatternSearchGUIUpdateToClient(slot); - } - - private void notifyPatternChanged() { - if (this.partController == null) { - return; - } - try { - EFabricatorMEChannel channel = this.partController.getChannel(); - if (channel != null && channel.getProxy().isActive()) { - channel.getProxy().getGrid().postEvent(new MENetworkCraftingPatternChange(channel, channel.getProxy().getNode())); - } - } catch (GridAccessException ignored) { - } - this.partController.recalculateEnergyUsage(); - } - - private void sendPatternSearchGUIUpdateToClient(final int slot) { - if (this.partController == null) { - return; - } - - List players = new ArrayList<>(); - world.playerEntities.stream() - .filter(EntityPlayerMP.class::isInstance) - .map(EntityPlayerMP.class::cast) - .forEach(playerMP -> { - if (playerMP.openContainer instanceof ContainerEFabricatorPatternSearch efPatternSearch) { - if (efPatternSearch.getOwner() == this.partController) { - players.add(playerMP); - } - } - }); - - if (!players.isEmpty()) { - PktEFabricatorPatternSearchGUIUpdate pktUpdate = new PktEFabricatorPatternSearchGUIUpdate( - PktEFabricatorPatternSearchGUIUpdate.UpdateType.SINGLE, - EFabricatorPatternData.of( - new EFabricatorPatternData.PatternData(getPos(), slot, patterns.getStackInSlot(slot)) - ) - ); - players.forEach(player -> NovaEngineeringCore.NET_CHANNEL.sendTo(pktUpdate, player)); - } - } - - @Override - public void validate() { - super.validate(); - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - ModularMachinery.EXECUTE_MANAGER.addSyncTask(this::refreshPatterns); - } - } - - @Override - public boolean hasCapability(@Nonnull final Capability capability, @Nullable final EnumFacing facing) { - return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing); - } - - @Nullable - @Override - public T getCapability(@Nonnull final Capability capability, @Nullable final EnumFacing facing) { - Capability cap = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; - if (capability == cap) { - return cap.cast(patterns); - } - return super.getCapability(capability, facing); - } - - @Override - public void readCustomNBT(final NBTTagCompound compound) { - super.readCustomNBT(compound); - patterns.readFromNBT(compound.getCompoundTag("patterns")); - } - - @Override - public void writeCustomNBT(final NBTTagCompound compound) { - super.writeCustomNBT(compound); - patterns.writeToNBT(compound, "patterns"); - } - -} diff --git a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorPatternBus.kt b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorPatternBus.kt new file mode 100644 index 00000000..86d42805 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorPatternBus.kt @@ -0,0 +1,174 @@ +package github.kasuminova.novaeng.common.tile.ecotech.efabricator + +import appeng.api.implementations.ICraftingPatternItem +import appeng.api.networking.crafting.ICraftingPatternDetails +import appeng.api.networking.events.MENetworkCraftingPatternChange +import appeng.me.GridAccessException +import appeng.tile.inventory.AppEngInternalInventory +import appeng.util.inv.IAEAppEngInventory +import appeng.util.inv.InvOperation +import com.glodblock.github.util.FluidCraftingPatternDetails +import github.kasuminova.mmce.common.util.PatternItemFilter +import github.kasuminova.novaeng.NovaEngineeringCore +import github.kasuminova.novaeng.common.container.ContainerEFabricatorPatternSearch +import github.kasuminova.novaeng.common.container.data.EFabricatorPatternData +import github.kasuminova.novaeng.common.network.PktEFabricatorPatternSearchGUIUpdate +import hellfirepvp.modularmachinery.ModularMachinery +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import java.util.Objects +import java.util.function.Consumer +import java.util.function.IntFunction +import java.util.stream.Collectors +import java.util.stream.IntStream +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.entity.player.EntityPlayerMP +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.EnumFacing +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.fml.common.FMLCommonHandler +import net.minecraftforge.items.CapabilityItemHandler +import net.minecraftforge.items.IItemHandler +import javax.annotation.Nonnull + +open class EFabricatorPatternBus : EFabricatorPart(), IAEAppEngInventory { + + companion object { + val PATTERN_SLOTS = 12 * 6 + } + + val patterns = AppEngInternalInventory(this, PATTERN_SLOTS, 1, PatternItemFilter.INSTANCE) + protected val details = ObjectArrayList(PATTERN_SLOTS) + + init { + // Initialize details... + IntStream.range(0, PATTERN_SLOTS).mapToObj(IntFunction { i: Int -> null }) + .forEach { e: ICraftingPatternDetails? -> details.add(e) } + } + + protected fun refreshPatterns() { + for (i in 0.. { + return details.stream() + .filter { obj: ICraftingPatternDetails? -> Objects.nonNull(obj) } + .collect(Collectors.toList()) + } + + val validPatterns: Int + get() = details.stream().filter { obj: ICraftingPatternDetails? -> Objects.nonNull(obj) }.count() + .toInt() + + override fun saveChanges() { + markNoUpdateSync() + } + + override fun onChangeInventory( + inv: IItemHandler?, + slot: Int, + mc: InvOperation?, + removedStack: ItemStack?, + newStack: ItemStack? + ) { + refreshPattern(slot) + notifyPatternChanged() + sendPatternSearchGUIUpdateToClient(slot) + } + + private fun notifyPatternChanged() { + if (this.partController == null) { + return + } + try { + val channel: EFabricatorMEChannel? = this.partController.channel + if (channel != null && channel.proxy.isActive) { + channel.proxy.grid + .postEvent(MENetworkCraftingPatternChange(channel, channel.proxy.node)) + } + } catch (ignored: GridAccessException) { + } + this.partController.recalculateEnergyUsage() + } + + private fun sendPatternSearchGUIUpdateToClient(slot: Int) { + if (this.partController == null) { + return + } + + val players = ObjectArrayList() + world.playerEntities.stream() + .filter { obj: EntityPlayer -> EntityPlayerMP::class.java.isInstance(obj) } + .map { obj: EntityPlayer -> EntityPlayerMP::class.java.cast(obj) } + .forEach { playerMP: EntityPlayerMP -> + val openContainer = playerMP.openContainer + if (openContainer is ContainerEFabricatorPatternSearch) { + if (openContainer.getOwner() === this.partController) { + players.add(playerMP) + } + } + } + + if (!players.isEmpty) { + val pktUpdate = PktEFabricatorPatternSearchGUIUpdate( + PktEFabricatorPatternSearchGUIUpdate.UpdateType.SINGLE, + EFabricatorPatternData.of( + EFabricatorPatternData.PatternData(getPos(), slot, patterns.getStackInSlot(slot)) + ) + ) + players.forEach(Consumer { player: EntityPlayerMP? -> + NovaEngineeringCore.NET_CHANNEL.sendTo( + pktUpdate, + player + ) + }) + } + } + + override fun validate() { + super.validate() + if (FMLCommonHandler.instance().getEffectiveSide().isServer) { + ModularMachinery.EXECUTE_MANAGER.addSyncTask { this.refreshPatterns() } + } + } + + override fun hasCapability(@Nonnull capability: Capability<*>, facing: EnumFacing?): Boolean { + return capability === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing) + } + + override fun getCapability(@Nonnull capability: Capability, facing: EnumFacing?): T? { + val cap = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY + if (capability === cap) { + return cap.cast(patterns) + } + return super.getCapability(capability, facing) + } + + override fun readCustomNBT(compound: NBTTagCompound) { + super.readCustomNBT(compound) + patterns.readFromNBT(compound.getCompoundTag("patterns")) + } + + override fun writeCustomNBT(compound: NBTTagCompound?) { + super.writeCustomNBT(compound) + patterns.writeToNBT(compound, "patterns") + } +} diff --git a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorWorker.java b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorWorker.java deleted file mode 100644 index e62c99d7..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorWorker.java +++ /dev/null @@ -1,442 +0,0 @@ -package github.kasuminova.novaeng.common.tile.ecotech.efabricator; - -import appeng.api.config.Actionable; -import appeng.api.networking.energy.IEnergyGrid; -import appeng.api.storage.data.IAEItemStack; -import appeng.api.storage.data.IItemList; -import appeng.me.GridAccessException; -import appeng.util.item.AEItemStack; -import github.kasuminova.novaeng.NovaEngineeringCore; -import github.kasuminova.novaeng.common.block.ecotech.efabricator.prop.WorkerStatus; -import github.kasuminova.novaeng.common.network.PktEFabricatorWorkerStatusUpdate; -import hellfirepvp.modularmachinery.common.util.ItemUtils; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import lombok.Getter; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraftforge.common.util.Constants; -import net.minecraftforge.fml.common.FMLCommonHandler; -import net.minecraftforge.fml.common.network.NetworkRegistry; - -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.Deque; -import java.util.List; - -public class EFabricatorWorker extends EFabricatorPart { - - public static final int MAX_ENERGY_CACHE = 500_000; - public static final int MAX_QUEUE_DEPTH = 32; - - public static final int ENERGY_USAGE = 100; - public static final int COOLANT_USAGE = 5; - - @Getter - protected final CraftingQueue queue = new CraftingQueue(); - - @Getter - protected WorkerStatus status = WorkerStatus.OFF; - protected int queueDepth = MAX_QUEUE_DEPTH; - @Getter - protected int energyCache = 0; - - protected long lastUpdateTick = 0L; - - public EFabricatorWorker() { - } - - public int getRemainingSpace() { - return this.getQueueDepth() - this.queue.size(); - } - - public synchronized int doWork() { - EFabricatorController controller = partController; - int coolantCache = controller.getCoolantCache(); - int energyUsage; - if (controller.isOverclocked() && !controller.isActiveCooling()) { - energyUsage = controller.getLevel().applyOverclockEnergyUsage(ENERGY_USAGE); - } else { - energyUsage = ENERGY_USAGE; - } - double energy = this.energyCache; - var c = controller.getChannel(); - IEnergyGrid grid = null; - if (c != null) { - try { - grid = c.proxy.getGrid().getCache(IEnergyGrid.class); - energy += grid.getStoredPower(); - } catch (GridAccessException ignored) { - - } - } - int parallelism = (int) Math.min(Math.max(controller.getAvailableParallelism(), 1), energy / energyUsage); - if (controller.isActiveCooling()) { - parallelism = Math.min(parallelism, coolantCache / COOLANT_USAGE); - } - - int completed = 0; - IItemList outputBuffer = controller.getOutputBuffer(); - CraftWork craftWork; - synchronized (outputBuffer) { - while ((parallelism > completed) && (craftWork = queue.poll()) != null) { - var workSize = parallelism - completed; - final var size = craftWork.size; - final CraftWork out; - if (size > workSize) { - out = craftWork.split(workSize); - queue.add(craftWork); - } else { - out = craftWork; - } - for (ItemStack remain : out.getRemaining()) { - if (!remain.isEmpty()) { - outputBuffer.add(AEItemStack.fromItemStack(remain)); - } - } - outputBuffer.add(AEItemStack.fromItemStack(out.getOutput())); - - completed += out.size; - } - } - - if (completed > 0) { - int in = energyUsage * completed; - if (in > energyCache) { - energyCache = 0; - in -= energyCache; - if (grid != null) { - synchronized (grid) { - grid.injectPower(in, Actionable.MODULATE); - } - } - } else { - energyCache -= in; - } - if (controller.isActiveCooling()) { - controller.consumeCoolant(COOLANT_USAGE * completed); - } - } - return completed; - } - - public void supplyEnergy(int energy) { - energyCache += energy; - } - - public int getMaxEnergyCache() { - return MAX_ENERGY_CACHE; - } - - public int getQueueDepth() { - EFabricatorController controller = getController(); - if (controller != null && controller.isOverclocked()) { - return controller.getLevel().applyOverclockQueueDepth(queueDepth); - } - return queueDepth; - } - - public void offerWork(final CraftWork craftWork) { - queue.add(craftWork); - } - - public boolean hasWork() { - return !queue.isEmpty(); - } - - public boolean isFull() { - return queue.size() >= getQueueDepth(); - } - - @Override - public void onAssembled() { - updateStatus(true); - super.onAssembled(); - } - - @Override - public void onDisassembled() { - updateStatus(true); - super.onDisassembled(); - } - - public void updateStatus(final boolean force) { - long prevUpdateTick = lastUpdateTick; - long updateTick = getWorld().getTotalWorldTime(); - - if (!force && status == WorkerStatus.RUN && prevUpdateTick + 20 >= updateTick) { - if (hasWork()) { - lastUpdateTick = updateTick; - } - return; - } - - if (getController() == null) { - if (status != WorkerStatus.OFF) { - setStatus(WorkerStatus.OFF); - } - } else if (hasWork()) { - if (status != WorkerStatus.RUN) { - setStatus(WorkerStatus.RUN); - } - } else { - if (status != WorkerStatus.ON) { - setStatus(WorkerStatus.ON); - } - } - lastUpdateTick = updateTick; - } - - public void setStatus(final WorkerStatus status) { - this.status = status; - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - markNoUpdateSync(); - } - } - - @Override - public void markNoUpdate() { - if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { - NovaEngineeringCore.NET_CHANNEL.sendToAllTracking( - new PktEFabricatorWorkerStatusUpdate(getPos(), status), - new NetworkRegistry.TargetPoint( - world.provider.getDimension(), - pos.getX(), pos.getY(), pos.getZ(), - -1) - ); - } - super.markNoUpdate(); - } - - @Override - public void readCustomNBT(final NBTTagCompound compound) { - queue.readFromNBT(compound); - energyCache = compound.getInteger("energyCache"); - status = WorkerStatus.values()[compound.getByte("status")]; - super.readCustomNBT(compound); - } - - @Override - public void writeCustomNBT(final NBTTagCompound compound) { - queue.writeToNBT(compound); - compound.setInteger("energyCache", energyCache); - compound.setByte("status", (byte) status.ordinal()); - super.writeCustomNBT(compound); - } - - public static class CraftingQueue { - - private static final String QUEUE_TAG = "Q"; - private static final String STACK_SET_TAG = "SS"; - private static final String STACK_SET_TAG_ID_PREFIX = "S#"; - private static final String STACK_SET_SIZE_TAG = "SSS"; - private static final String REPEAT_TAG = "R"; - - @Getter - private final Deque queue = new ArrayDeque<>(); - private int size = 0; - - public int size() { - return size; - } - - public boolean isEmpty() { - return queue.isEmpty(); - } - - public void add(final CraftWork craftWork) { - queue.add(craftWork); - size += craftWork.size; - } - - public CraftWork poll() { - var i = queue.poll(); - if (i != null) { - size -= i.size; - } else { - size = 0; - } - return i; - } - - public CraftWork peek() { - return queue.peek(); - } - - public NBTTagCompound writeToNBT(final NBTTagCompound nbt) { - if (queue.isEmpty()) { - return nbt; - } - - List stackSet = new ObjectArrayList<>(); - - // Queue - NBTTagList queueTag = new NBTTagList(); - CraftWork prev = null; - int repeat = 0; - for (CraftWork craftWork : queue) { - if (prev != null && prev.equals(craftWork)) { - repeat++; - continue; - } - if (repeat > 0) { - queueTag.getCompoundTagAt(queueTag.tagCount() - 1).setShort(REPEAT_TAG, (short) repeat); - repeat = 0; - } - queueTag.appendTag(craftWork.writeToNBT(stackSet)); - prev = craftWork; - } - if (repeat > 0) { - queueTag.getCompoundTagAt(queueTag.tagCount() - 1).setShort(REPEAT_TAG, (short) repeat); - } - nbt.setTag(QUEUE_TAG, queueTag); - - // StackSet - NBTTagCompound stackSetTag = new NBTTagCompound(); - for (int i = 0; i < stackSet.size(); i++) { - final ItemStack stack = stackSet.get(i); - if (!stack.isEmpty()) { - stackSetTag.setTag(STACK_SET_TAG_ID_PREFIX + i, stack.serializeNBT()); - } - } - nbt.setTag(STACK_SET_TAG, stackSetTag); - nbt.setInteger(STACK_SET_SIZE_TAG, stackSet.size()); - - return nbt; - } - - public void readFromNBT(final NBTTagCompound nbt) { - queue.clear(); - List stackSet = new ObjectArrayList<>(); - - // StackSet - NBTTagCompound stackSetTag = nbt.getCompoundTag(STACK_SET_TAG); - for (int i = 0; i < nbt.getInteger(STACK_SET_SIZE_TAG); i++) { - stackSet.add(new ItemStack(stackSetTag.getCompoundTag(STACK_SET_TAG_ID_PREFIX + i))); - } - - // Queue - NBTTagList queueTag = nbt.getTagList(QUEUE_TAG, Constants.NBT.TAG_COMPOUND); - for (int i = 0; i < queueTag.tagCount(); i++) { - NBTTagCompound tagAt = queueTag.getCompoundTagAt(i); - CraftWork work = new CraftWork(tagAt, stackSet); - queue.add(work); - short repeat = tagAt.getShort(REPEAT_TAG); - for (short r = 0; r < repeat; r++) { - queue.add(work.copy()); - } - } - } - - } - - @Getter - public static class CraftWork { - - private static final String REMAIN_TAG_PREFIX = "R#"; - private static final String REMAIN_SIZE_TAG = REMAIN_TAG_PREFIX + "S"; - private static final String OUTPUT_TAG = "O"; - private static final String SIZE = "Z"; - - private final ItemStack[] remaining; - private final ItemStack output; - private int size; - - public CraftWork(final ItemStack[] remaining, final ItemStack output, final int size) { - this.remaining = remaining; - this.output = output; - this.size = Math.max(1, size); - } - - public CraftWork(final NBTTagCompound nbt, final List stackSet) { - remaining = new ItemStack[nbt.getByte(REMAIN_SIZE_TAG)]; - for (int remainIdx = 0; remainIdx < remaining.length; remainIdx++) { - int setIdx = nbt.hasKey(REMAIN_TAG_PREFIX + remainIdx) ? nbt.getInteger(REMAIN_TAG_PREFIX + remainIdx) : -1; - remaining[remainIdx] = setIdx == -1 ? ItemStack.EMPTY : stackSet.get(setIdx); - } - output = stackSet.get(nbt.getInteger(OUTPUT_TAG)); - size = Math.max(1, nbt.getInteger(SIZE)); - } - - private static boolean matchStacksStrict(final ItemStack stack1, final ItemStack stack2) { - return ItemUtils.matchStacks(stack1, stack2) && stack1.getCount() == stack2.getCount(); - } - - public CraftWork split(int amount) { - final var i = Math.min(amount, this.size); - if (i > 0) { - final var inputs = new ItemStack[this.remaining.length]; - for (int ii = 0; ii < remaining.length; ii++) { - inputs[ii] = remaining[ii].splitStack(i); - } - final var output = this.output.copy(); - final var eachOutput = this.output.getCount() / size; - final var outCount = i * eachOutput; - output.setCount(outCount); - this.output.shrink(outCount); - size -= i; - return new CraftWork(inputs, output, i); - } else { - final var inputs = new ItemStack[this.remaining.length]; - Arrays.fill(inputs, ItemStack.EMPTY); - return new CraftWork(inputs, ItemStack.EMPTY, 0); - } - } - - public NBTTagCompound writeToNBT(final List stackSet) { - NBTTagCompound nbt = new NBTTagCompound(); - - // Input. - nbt.setByte(REMAIN_SIZE_TAG, (byte) remaining.length); - remain: - for (int remainIdx = 0; remainIdx < remaining.length; remainIdx++) { - final ItemStack remain = remaining[remainIdx]; - if (remain.isEmpty()) { - continue; - } - - for (int setIdx = 0; setIdx < stackSet.size(); setIdx++) { - if (matchStacksStrict(remain, stackSet.get(setIdx))) { - nbt.setShort(REMAIN_TAG_PREFIX + remainIdx, (short) setIdx); - continue remain; - } - } - - stackSet.add(remain); - nbt.setShort(REMAIN_TAG_PREFIX + remainIdx, (short) (stackSet.size() - 1)); - } - - // Output - for (int setIdx = 0; setIdx < stackSet.size(); setIdx++) { - if (matchStacksStrict(output, stackSet.get(setIdx))) { - nbt.setShort(OUTPUT_TAG, (short) setIdx); - return nbt; - } - } - - stackSet.add(output); - nbt.setShort(OUTPUT_TAG, (short) (stackSet.size() - 1)); - nbt.setInteger(SIZE, size); - return nbt; - } - - public CraftWork copy() { - ItemStack[] remaining = Arrays.stream(this.remaining).map(ItemStack::copy).toArray(ItemStack[]::new); - return new CraftWork(remaining, output.copy(), this.size); - } - - @Override - public boolean equals(final Object obj) { - if (obj instanceof final CraftWork craftWork) { - for (int i = 0; i < remaining.length; i++) { - if (!matchStacksStrict(remaining[i], craftWork.remaining[i])) { - return false; - } - } - return matchStacksStrict(output, craftWork.output); - } - return false; - } - - } -} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorWorker.kt b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorWorker.kt new file mode 100644 index 00000000..d52c3ed8 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/tile/ecotech/efabricator/EFabricatorWorker.kt @@ -0,0 +1,442 @@ +package github.kasuminova.novaeng.common.tile.ecotech.efabricator + +import appeng.api.config.Actionable +import appeng.api.networking.energy.IEnergyGrid +import appeng.api.storage.data.IAEItemStack +import appeng.api.storage.data.IItemList +import appeng.me.GridAccessException +import appeng.util.item.AEItemStack +import github.kasuminova.novaeng.NovaEngineeringCore +import github.kasuminova.novaeng.common.block.ecotech.efabricator.prop.WorkerStatus +import github.kasuminova.novaeng.common.network.PktEFabricatorWorkerStatusUpdate +import hellfirepvp.modularmachinery.common.util.ItemUtils +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import java.util.ArrayDeque +import java.util.Arrays +import java.util.Deque +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.nbt.NBTTagList +import net.minecraftforge.common.util.Constants +import net.minecraftforge.fml.common.FMLCommonHandler +import net.minecraftforge.fml.common.network.NetworkRegistry +import kotlin.math.max +import kotlin.math.min + +open class EFabricatorWorker : EFabricatorPart() { + + companion object { + const val MAX_ENERGY_CACHE: Int = 500000 + const val MAX_QUEUE_DEPTH: Int = 32 + + const val ENERGY_USAGE: Int = 100 + const val COOLANT_USAGE: Int = 5 + } + + val queue = CraftingQueue() + + var status = WorkerStatus.OFF + set(value) { + field = value + if (FMLCommonHandler.instance().getEffectiveSide().isServer) { + markNoUpdateSync() + } + } + var queueDepth = MAX_QUEUE_DEPTH + get() { + val controller = getController() + if (controller != null && controller.overclocked) { + return controller.level.applyOverclockQueueDepth(field) + } + return field + } + + var energyCache = 0 + + var updateTick = 0L + + val remainingSpace: Int + get() = this.queueDepth - this.queue.size() + + fun getMaxEnergyCache(): Int { + return MAX_ENERGY_CACHE + } + + @Synchronized + fun doWork(): Int { + val controller = partController + val coolantCache = controller.coolantCache + val energyUsage: Int = if (controller.overclocked && !controller.activeCooling) { + controller.level.applyOverclockEnergyUsage(ENERGY_USAGE) + } else { + ENERGY_USAGE + } + var energy = this.energyCache.toDouble() + val c = controller.channel + var grid: IEnergyGrid? = null + if (c != null) { + try { + grid = c.proxy.grid.getCache(IEnergyGrid::class.java) + energy += grid.storedPower + } catch (ignored: GridAccessException) { + } + } + var parallelism = min(max(controller.availableParallelism, 1).toDouble(), energy / energyUsage).toInt() + if (controller.activeCooling) { + parallelism = min(parallelism, coolantCache / COOLANT_USAGE) + } + + var completed = 0 + val outputBuffer: IItemList = controller.outputBuffer + var craftWork: CraftWork + synchronized(outputBuffer) { + while ((parallelism > completed) && !queue.isEmpty) { + craftWork = queue.poll() + val workSize = parallelism - completed + val size = craftWork.size + val out: CraftWork + if (size > workSize) { + out = craftWork.split(workSize) + queue.add(craftWork) + } else { + out = craftWork + } + for (remain in out.remaining) { + if (!remain.isEmpty) { + outputBuffer.add(AEItemStack.fromItemStack(remain)) + } + } + outputBuffer.add(AEItemStack.fromItemStack(out.output)) + + completed += out.size + } + } + + if (completed > 0) { + var `in` = energyUsage * completed + if (`in` > energyCache) { + `in` -= energyCache + energyCache = 0 + if (grid != null) { + synchronized(grid) { + grid.injectPower(`in`.toDouble(), Actionable.MODULATE) + } + } + } else { + energyCache -= `in` + } + if (controller.activeCooling) { + controller.consumeCoolant(COOLANT_USAGE * completed) + } + } + return completed + } + + fun supplyEnergy(energy: Int) { + energyCache += energy + } + + fun offerWork(craftWork: CraftWork) { + queue.add(craftWork) + } + + fun hasWork(): Boolean { + return !queue.isEmpty + } + + val isFull: Boolean + get() = queue.size() >= queueDepth + + override fun onAssembled() { + updateStatus(true) + super.onAssembled() + } + + override fun onDisassembled() { + updateStatus(true) + super.onDisassembled() + } + + fun updateStatus(force: Boolean) { + val prevUpdateTick = updateTick + val updateTick = getWorld().totalWorldTime + + if (!force && status == WorkerStatus.RUN && prevUpdateTick + 20 >= updateTick) { + if (hasWork()) { + this@EFabricatorWorker.updateTick = updateTick + } + return + } + + if (controller == null) { + if (status != WorkerStatus.OFF) { + status = WorkerStatus.OFF + } + } else if (hasWork()) { + if (status != WorkerStatus.RUN) { + status = WorkerStatus.RUN + } + } else { + if (status != WorkerStatus.ON) { + status = WorkerStatus.ON + } + } + this@EFabricatorWorker.updateTick = updateTick + } + + override fun markNoUpdate() { + if (FMLCommonHandler.instance().getEffectiveSide().isServer) { + NovaEngineeringCore.NET_CHANNEL.sendToAllTracking( + PktEFabricatorWorkerStatusUpdate(getPos(), status), + NetworkRegistry.TargetPoint( + world.provider.dimension, + pos.x.toDouble(), pos.y.toDouble(), pos.z.toDouble(), + -1.0 + ) + ) + } + super.markNoUpdate() + } + + override fun readCustomNBT(compound: NBTTagCompound) { + queue.readFromNBT(compound) + energyCache = compound.getInteger("energyCache") + status = WorkerStatus.entries[compound.getByte("status").toInt()] + super.readCustomNBT(compound) + } + + override fun writeCustomNBT(compound: NBTTagCompound) { + queue.writeToNBT(compound) + compound.setInteger("energyCache", energyCache) + compound.setByte("status", status.ordinal.toByte()) + super.writeCustomNBT(compound) + } + + class CraftingQueue { + val queue: Deque = ArrayDeque() + private var size = 0 + + fun size(): Int { + return size + } + + val isEmpty: Boolean + get() = queue.isEmpty() + + fun add(craftWork: CraftWork) { + queue.add(craftWork) + size += craftWork.size + } + + fun poll(): CraftWork { + val i = queue.poll() + if (i != null) { + size -= i.size + } else { + size = 0 + } + return i + } + + fun peek(): CraftWork? { + return queue.peek() + } + + fun writeToNBT(nbt: NBTTagCompound): NBTTagCompound { + if (queue.isEmpty()) { + return nbt + } + + val stackSet = ObjectArrayList() + + // Queue + val queueTag = NBTTagList() + var prev: CraftWork? = null + var repeat = 0 + for (craftWork in queue) { + if (prev != null && prev == craftWork) { + repeat++ + continue + } + if (repeat > 0) { + queueTag.getCompoundTagAt(queueTag.tagCount() - 1).setShort(REPEAT_TAG, repeat.toShort()) + repeat = 0 + } + queueTag.appendTag(craftWork.writeToNBT(stackSet)) + prev = craftWork + } + if (repeat > 0) { + queueTag.getCompoundTagAt(queueTag.tagCount() - 1).setShort(REPEAT_TAG, repeat.toShort()) + } + nbt.setTag(QUEUE_TAG, queueTag) + + // StackSet + val stackSetTag = NBTTagCompound() + for (i in stackSet.indices) { + val stack = stackSet[i] + if (!stack.isEmpty) { + stackSetTag.setTag(STACK_SET_TAG_ID_PREFIX + i, stack.serializeNBT()) + } + } + nbt.setTag(STACK_SET_TAG, stackSetTag) + nbt.setInteger(STACK_SET_SIZE_TAG, stackSet.size) + + return nbt + } + + fun readFromNBT(nbt: NBTTagCompound) { + queue.clear() + val stackSet = ObjectArrayList() + + // StackSet + val stackSetTag = nbt.getCompoundTag(STACK_SET_TAG) + for (i in 0.. + val output: ItemStack + internal var size: Int + + constructor(remaining: Array, output: ItemStack, size: Int) { + this.remaining = remaining + this.output = output + this.size = max(1, size) + } + + constructor(nbt: NBTTagCompound, stackSet: MutableList) { + remaining = Array( + nbt.getByte(REMAIN_SIZE_TAG).toInt() + ) { i -> ItemStack.EMPTY } + for (remainIdx in remaining.indices) { + val setIdx = + if (nbt.hasKey(REMAIN_TAG_PREFIX + remainIdx)) nbt.getInteger(REMAIN_TAG_PREFIX + remainIdx) else -1 + remaining[remainIdx] = if (setIdx == -1) ItemStack.EMPTY else stackSet[setIdx] + } + output = stackSet[nbt.getInteger(OUTPUT_TAG)] + size = max(1, nbt.getInteger(SIZE)) + } + + fun split(amount: Int): CraftWork { + val i = min(amount, this.size) + if (i > 0) { + val inputs: Array = Array( + this.remaining.size + ) { i -> ItemStack.EMPTY } + for (ii in remaining.indices) { + inputs[ii] = remaining[ii].splitStack(i) + } + val output = this.output.copy() + val eachOutput = this.output.count / size + val outCount = i * eachOutput + output.setCount(outCount) + this.output.shrink(outCount) + size -= i + return CraftWork(inputs, output, i) + } else { + val inputs = Array(this.remaining.size) { i -> ItemStack.EMPTY } + return CraftWork(inputs, ItemStack.EMPTY, 0) + } + } + + fun writeToNBT(stackSet: MutableList): NBTTagCompound { + val nbt = NBTTagCompound() + + // Input. + nbt.setByte(REMAIN_SIZE_TAG, remaining.size.toByte()) + remain@ for (remainIdx in remaining.indices) { + val remain = remaining[remainIdx] + if (remain.isEmpty) { + continue + } + + for (setIdx in stackSet.indices) { + if (matchStacksStrict(remain, stackSet[setIdx])) { + nbt.setShort(REMAIN_TAG_PREFIX + remainIdx, setIdx.toShort()) + continue@remain + } + } + + stackSet.add(remain) + nbt.setShort(REMAIN_TAG_PREFIX + remainIdx, (stackSet.size - 1).toShort()) + } + + // Output + for (setIdx in stackSet.indices) { + if (matchStacksStrict(output, stackSet[setIdx])) { + nbt.setShort(OUTPUT_TAG, setIdx.toShort()) + return nbt + } + } + + stackSet.add(output) + nbt.setShort(OUTPUT_TAG, (stackSet.size - 1).toShort()) + nbt.setInteger(SIZE, size) + return nbt + } + + fun copy(): CraftWork { + val remaining = Arrays.stream(this.remaining) + .map { obj: ItemStack -> obj.copy() } + .toArray { + Array( + 0 + ) { ItemStack.EMPTY } + } + return CraftWork(remaining, output.copy(), this.size) + } + + override fun equals(other: Any?): Boolean { + if (other is CraftWork) { + for (i in remaining.indices) { + if (!matchStacksStrict(remaining[i], other.remaining[i])) { + return false + } + } + return matchStacksStrict(output, other.output) + } + return false + } + + companion object { + private const val REMAIN_TAG_PREFIX = "R#" + private val REMAIN_SIZE_TAG = REMAIN_TAG_PREFIX + "S" + private const val OUTPUT_TAG = "O" + private const val SIZE = "Z" + + private fun matchStacksStrict(stack1: ItemStack, stack2: ItemStack): Boolean { + return ItemUtils.matchStacks(stack1, stack2) && stack1.count == stack2.count + } + } + + override fun hashCode(): Int { + var result = size + result = 31 * result + remaining.contentHashCode() + result = 31 * result + output.hashCode() + return result + } + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/trait/Register.java b/src/main/java/github/kasuminova/novaeng/common/trait/Register.java deleted file mode 100644 index 9480785b..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/trait/Register.java +++ /dev/null @@ -1,23 +0,0 @@ -package github.kasuminova.novaeng.common.trait; - -import github.kasuminova.novaeng.common.enchantment.MagicBreaking; -import github.kasuminova.novaeng.common.item.ItemBasic; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import slimeknights.tconstruct.library.modifiers.Modifier; -import slimeknights.tconstruct.tools.AbstractToolPulse; - -import java.util.List; - -public class Register extends AbstractToolPulse { - - public static Register TRAITREGISTER = new Register(); - public List modifierTraitsF = new ObjectArrayList<>(); - public List modifierTraitsT = new ObjectArrayList<>(); - - public void registerModifiers() { - TraitMagicBreaking traitMagicBreaking = registerModifier(new TraitMagicBreaking()); - traitMagicBreaking.addItem(ItemBasic.getItem(MagicBreaking.MAGICBREAKING.getId() + "_stone"), 1, 1); - - modifierTraitsF.add(traitMagicBreaking); - } -} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/trait/Register.kt b/src/main/java/github/kasuminova/novaeng/common/trait/Register.kt new file mode 100644 index 00000000..919eacca --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/trait/Register.kt @@ -0,0 +1,20 @@ +package github.kasuminova.novaeng.common.trait + +import github.kasuminova.novaeng.common.enchantment.MagicBreaking +import github.kasuminova.novaeng.common.item.ItemBasic +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import slimeknights.tconstruct.library.modifiers.Modifier +import slimeknights.tconstruct.tools.AbstractToolPulse + +object Register : AbstractToolPulse() { + + var modifierTraitsF: MutableList = ObjectArrayList() + var modifierTraitsT: MutableList = ObjectArrayList() + + fun registerModifiers() { + val traitMagicBreaking = registerModifier(TraitMagicBreaking()) + traitMagicBreaking.addItem(ItemBasic.getItem(MagicBreaking.MAGICBREAKING.id + "_stone"), 1, 1) + + modifierTraitsF.add(traitMagicBreaking) + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/util/AssemblyBlockArray.kt b/src/main/java/github/kasuminova/novaeng/common/util/AssemblyBlockArray.kt new file mode 100644 index 00000000..086a1c2e --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/util/AssemblyBlockArray.kt @@ -0,0 +1,308 @@ +package github.kasuminova.novaeng.common.util + +import appeng.api.AEApi +import appeng.api.config.Actionable +import appeng.api.networking.storage.IStorageGrid +import appeng.api.storage.IMEMonitor +import appeng.api.storage.channels.IFluidStorageChannel +import appeng.api.storage.channels.IItemStorageChannel +import appeng.api.storage.data.IAEFluidStack +import appeng.api.storage.data.IAEItemStack +import appeng.helpers.WirelessTerminalGuiObject +import appeng.me.helpers.PlayerSource +import com.circulation.random_complement.common.util.MEHandler +import github.kasuminova.novaeng.common.util.NEWMachineAssemblyManager.Ingredient +import github.kasuminova.novaeng.common.util.NEWMachineAssemblyManager.OperatingStatus +import hellfirepvp.modularmachinery.common.util.BlockArray +import hellfirepvp.modularmachinery.common.util.MiscUtils +import ink.ikx.mmce.common.assembly.MachineAssembly +import ink.ikx.mmce.common.utils.FluidUtils +import ink.ikx.mmce.common.utils.StackUtils +import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import net.minecraft.block.BlockLiquid +import net.minecraft.block.material.Material +import net.minecraft.block.state.IBlockState +import net.minecraft.entity.player.EntityPlayerMP +import net.minecraft.init.Blocks +import net.minecraft.init.Items +import net.minecraft.item.ItemStack +import net.minecraft.util.EnumFacing +import net.minecraft.util.Tuple +import net.minecraft.util.math.BlockPos +import net.minecraft.util.text.TextComponentTranslation +import net.minecraft.world.World +import net.minecraftforge.common.util.BlockSnapshot +import net.minecraftforge.event.ForgeEventFactory +import net.minecraftforge.fluids.BlockFluidBase +import net.minecraftforge.fluids.FluidRegistry +import net.minecraftforge.fluids.FluidStack +import net.minecraftforge.fluids.FluidUtil +import net.minecraftforge.fluids.UniversalBucket +import net.minecraftforge.fluids.capability.IFluidHandlerItem +import java.util.ArrayDeque +import java.util.Queue +import java.util.function.Function + +class AssemblyBlockArray : BlockArray { + + companion object { + private val material = + Object2ReferenceOpenHashMap>>() + + /** + * MachineAssembly#getFluidHandlerItems(List) + */ + private fun getFluidHandlerItems(inventory: List): List { + val fluidHandlers = ObjectArrayList() + for (invStack in inventory) { + val item = invStack.item + if (item is UniversalBucket || item === Items.LAVA_BUCKET || item === Items.WATER_BUCKET) { + continue + } + if (!FluidUtils.isFluidHandler(invStack)) { + continue + } + val fluidHandler = FluidUtil.getFluidHandler(invStack) + if (fluidHandler != null) { + fluidHandlers.add(fluidHandler) + } + } + return fluidHandlers + } + } + + var usingAE = false + var ignoreFluids = false + var missing = 0 + private var queue: Queue? = null + + constructor() : super() + + constructor(uid: Long) : super(uid) + + constructor(other: BlockArray) : super(other) + + constructor(other: BlockArray, offset: BlockPos) : super(other, offset) + + fun copy(): AssemblyBlockArray { + return AssemblyBlockArray(this) + } + + fun offset(offset: BlockPos): AssemblyBlockArray { + return AssemblyBlockArray(this, offset) + } + + fun end() { + this.pattern.clear() + queue = null + } + + fun start(usingAE: Boolean = true, ignoreFluids: Boolean = true) { + queue = ArrayDeque() + val l = Function { b: BlockInformation -> ObjectArrayList>() } + for (entry in this.pattern.entries) { + queue!!.add(entry.key) + val info = entry.value + if (material.containsKey(info)) continue + for (stateDescriptor in info.matchingStates) { + for (state in stateDescriptor.applicable) { + val block = state.getBlock() + val ingredient = if (block is BlockFluidBase) { + Ingredient( + FluidStack(block.fluid, 1000) + ) + } else if (block is BlockLiquid) { + val material1 = state.getMaterial() + if (material1 === Material.LAVA) { + Ingredient(FluidStack(FluidRegistry.LAVA, 1000)) + } else Ingredient(FluidStack(FluidRegistry.WATER, 1000)) + } else { + Ingredient(StackUtils.getStackFromBlockState(state)) + } + material.computeIfAbsent(info, l).add(Tuple(ingredient, state)) + } + } + } + } + + fun isFluid(state: IBlockState): Boolean { + val block = state.getBlock() + return block is BlockLiquid || block is BlockFluidBase + } + + fun assemblyBlock(world: World, player: EntityPlayerMP): OperatingStatus { + val pos = queue!!.poll() ?: return OperatingStatus.COMPLETE + val info: BlockInformation = synchronized(pattern) { + this.pattern.remove(pos) ?: return OperatingStatus.ALREADY_EXISTS + } + + if (player.isCreative) { + placeBlock(player, world, pos, info.sampleState) + return OperatingStatus.SUCCESS + } + + val oldState = world.getBlockState(pos) + if (oldState != null && + (oldState.getBlock() !== Blocks.AIR + && !(ignoreFluids && isFluid(oldState))) + ) { + return if (matchesState(info, oldState)) { + OperatingStatus.ALREADY_EXISTS + } else { + player.sendMessage( + TextComponentTranslation( + "message.assembly.tip.cannot_replace", + MiscUtils.posToString(pos) + ) + ) + OperatingStatus.FAILURE + } + } + + val list = material[info] ?: throw RuntimeException("Unknown BlockInformation") + + var hasAE = false + var wobj: WirelessTerminalGuiObject? = null + var items: IMEMonitor? = null + var fluids: IMEMonitor? = null + + if (usingAE) { + wobj = MEHandler.getTerminalGuiObject(player) + wobj?.actionableNode?.grid?.let { + val grid = it.getCache(IStorageGrid::class.java) + items = grid.getInventory( + AEApi.instance().storage() + .getStorageChannel(IItemStorageChannel::class.java) + ) + fluids = grid.getInventory( + AEApi.instance().storage() + .getStorageChannel(IFluidStorageChannel::class.java) + ) + hasAE = true + } + } + val itemInventory = player.inventory.mainInventory + val fluidInventory = getFluidHandlerItems(itemInventory) + for (ingredientAndIBlockState in list) { + val ingredient = ingredientAndIBlockState.first + if (ingredient.isItem) { + if (ingredient.itemStack.isEmpty) continue + if (MachineAssembly.consumeInventoryItem( + ingredient.itemStack, + itemInventory + ) + ) { + placeBlock(player, world, pos, ingredientAndIBlockState.getSecond()) + return OperatingStatus.SUCCESS + } + } else { + if (MachineAssembly.consumeInventoryFluid( + ingredient.fluidStack, + fluidInventory + ) + ) { + placeBlock(player, world, pos, ingredientAndIBlockState.getSecond()) + return OperatingStatus.SUCCESS + } + } + } + if (hasAE) { + for (ingredientAndIBlockState in list) { + val ingredient = ingredientAndIBlockState.first + if (ingredient.isItem) { + if (ingredient.itemStack.isEmpty) continue + val item = items!!.extractItems( + ingredient.aEItemStack, + Actionable.MODULATE, + PlayerSource(player, wobj) + ) + if (item == null || item.stackSize == 0L) continue + placeBlock(player, world, pos, ingredientAndIBlockState.getSecond()) + return OperatingStatus.SUCCESS + } else { + val fluid = fluids!!.extractItems( + ingredient.aEFluidStack, + Actionable.SIMULATE, + PlayerSource(player, wobj) + ) + if (fluid == null || fluid.stackSize < 1000) continue + fluids.extractItems( + ingredient.aEFluidStack, + Actionable.MODULATE, + PlayerSource(player, wobj) + ) + placeBlock(player, world, pos, ingredientAndIBlockState.getSecond()) + return OperatingStatus.SUCCESS + } + } + } + if (oldState.block == Blocks.AIR && matchesState(info, oldState)) { + return OperatingStatus.ALREADY_EXISTS + } + if (missing > 0) { + --missing + return OperatingStatus.SUCCESS + } + player.sendMessage( + TextComponentTranslation( + "message.assembly.tip.missing", + MiscUtils.posToString(pos) + ) + ) + return OperatingStatus.FAILURE + } + + private fun placeBlock(player: EntityPlayerMP, world: World, pos: BlockPos, state: IBlockState) { + player.getServer()!!.addScheduledTask { + if (!player.isCreative && ForgeEventFactory.onBlockPlace( + player, + BlockSnapshot(world, pos, state), + EnumFacing.UP + ).isCanceled + ) { + player.sendMessage( + TextComponentTranslation( + "message.assembly.tip.missing", + MiscUtils.posToString(pos) + ) + ) + player.inventory.placeItemBackInInventory( + world, + StackUtils.getStackFromBlockState(state) + ) + } else { + val flags = 0b10011 + val chunk = world.getChunk(pos) + var blockSnapshot: BlockSnapshot? = null + if (world.captureBlockSnapshots) + blockSnapshot = BlockSnapshot.getBlockSnapshot(world, pos, flags) + val iblockstate = chunk.setBlockState(pos, state) + + if (iblockstate != null) { + if (blockSnapshot == null) { + world.markAndNotifyBlock(pos, chunk, iblockstate, state, flags) + } else { + world.capturedBlockSnapshots.add(blockSnapshot) + } + } + } + } + } + + fun matchesState(info: BlockInformation, state: IBlockState): Boolean { + val atBlock = state.getBlock() + val atMeta = atBlock.getMetaFromState(state) + + for (descriptor in info.matchingStates) { + for (applicable in descriptor.applicable) { + val type = applicable.getBlock() + val meta = type.getMetaFromState(applicable) + if (type == atBlock && meta == atMeta) { + return true + } + } + } + return false + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/util/AutoCraftingQueue.kt b/src/main/java/github/kasuminova/novaeng/common/util/AutoCraftingQueue.kt new file mode 100644 index 00000000..f0b7493c --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/util/AutoCraftingQueue.kt @@ -0,0 +1,89 @@ +package github.kasuminova.novaeng.common.util + +import appeng.api.networking.crafting.ICraftingGrid +import appeng.api.networking.crafting.ICraftingJob +import appeng.api.util.AEPartLocation +import appeng.container.ContainerOpenContext +import appeng.core.AELog +import appeng.me.helpers.PlayerSource +import appeng.util.item.AEItemStack +import com.circulation.random_complement.common.util.MEHandler +import github.kasuminova.novaeng.NovaEngineeringCore +import github.kasuminova.novaeng.common.CommonProxy +import github.kasuminova.novaeng.common.container.ContainerNEWCraftConfirm +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import java.util.Queue +import java.util.concurrent.Future +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.item.ItemStack + +class AutoCraftingQueue { + + companion object { + private val allQueue = Object2ObjectOpenHashMap() + + fun setQueueAndStrat(itemQueue: Queue, player: EntityPlayer) { + val q: AutoCraftingQueue = allQueue.computeIfAbsent(player) { p -> AutoCraftingQueue() } + q.queue = itemQueue + q.executionQueue(player) + } + + fun getQueue(player: EntityPlayer): AutoCraftingQueue? { + return allQueue[player] + } + } + + private var queue: Queue = EmptyQueue.empty() + + fun clearQueue() { + queue.clear() + } + + fun executionQueue(player: EntityPlayer): Boolean { + queue.poll()?.let { item -> + val obj = MEHandler.getTerminalGuiObject(player) + obj?.actionableNode?.let { node -> + val g = node.grid + var futureJob: Future? = null + + try { + val cg: ICraftingGrid = g.getCache(ICraftingGrid::class.java) + futureJob = cg.beginCraftingJob( + player.world, + g, + PlayerSource(player, obj), + AEItemStack.fromItemStack(item)?.setStackSize(item.count.toLong()), + null + ) + + player.openGui( + NovaEngineeringCore.instance, + CommonProxy.GuiType.AUTO_CRAFTGUI.ordinal, + player.world, + obj.inventorySlot, + if (obj.isBaubleSlot) 1 else 0, + Int.MIN_VALUE + ) + + val ccc = player.openContainer + + if (ccc is ContainerNEWCraftConfirm) { + val ctx = ContainerOpenContext(null) + ctx.side = AEPartLocation.INTERNAL + + ccc.openContext = ctx + ccc.isAutoStart = false + ccc.setJob(futureJob) + ccc.detectAndSendChanges() + } + return true + } catch (e: Throwable) { + futureJob?.cancel(true) + AELog.debug(e) + } + + } + } + return false + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/util/EPartMap.java b/src/main/java/github/kasuminova/novaeng/common/util/EPartMap.java index 74f25316..6b7f10af 100644 --- a/src/main/java/github/kasuminova/novaeng/common/util/EPartMap.java +++ b/src/main/java/github/kasuminova/novaeng/common/util/EPartMap.java @@ -11,7 +11,6 @@ import java.util.Map; import java.util.function.Consumer; -@SuppressWarnings("unchecked") public class EPartMap

> { protected final Map, List

> parts = new Reference2ObjectOpenHashMap<>(); diff --git a/src/main/java/github/kasuminova/novaeng/common/util/EmptyQueue.kt b/src/main/java/github/kasuminova/novaeng/common/util/EmptyQueue.kt new file mode 100644 index 00000000..29cccfec --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/util/EmptyQueue.kt @@ -0,0 +1,81 @@ +package github.kasuminova.novaeng.common.util + +import it.unimi.dsi.fastutil.objects.ObjectLists +import java.util.Queue + +class EmptyQueue : Queue { + + companion object { + private val empty: EmptyQueue<*> = EmptyQueue() + + @Suppress("UNCHECKED_CAST") + fun empty(): EmptyQueue { + return empty as EmptyQueue + } + } + + private constructor() + + override fun add(e: E?): Boolean { + return false + } + + override fun offer(e: E?): Boolean { + return false + } + + override fun remove(): E? { + return null + } + + override fun poll(): E? { + return null + } + + override fun element(): E? { + return null + } + + override fun peek(): E? { + return null + } + + override fun iterator(): MutableIterator { + return ObjectLists.emptyList().iterator() + } + + override fun remove(element: E?): Boolean { + return false + } + + override fun addAll(elements: Collection): Boolean { + return false + } + + override fun removeAll(elements: Collection): Boolean { + return false + } + + override fun retainAll(elements: Collection): Boolean { + return false + } + + override fun clear() { + + } + + override val size: Int + get() = 0 + + override fun isEmpty(): Boolean { + return true + } + + override fun contains(element: E?): Boolean { + return false + } + + override fun containsAll(elements: Collection): Boolean { + return false + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/util/MachineCoolants.java b/src/main/java/github/kasuminova/novaeng/common/util/MachineCoolants.java index e5779615..99c0fdf9 100644 --- a/src/main/java/github/kasuminova/novaeng/common/util/MachineCoolants.java +++ b/src/main/java/github/kasuminova/novaeng/common/util/MachineCoolants.java @@ -18,7 +18,7 @@ public class MachineCoolants { private final Map coolants = new Reference2ObjectLinkedOpenHashMap<>(); public void init() { - Fluid water = FluidRegistry.getFluid("water"); + Fluid water = FluidRegistry.WATER; Fluid steam = FluidRegistry.getFluid("steam"); if (steam != null) { coolants.put(water, new Coolant(new FluidStack(water, 1), new FluidStack(steam, 1), 15)); diff --git a/src/main/java/github/kasuminova/novaeng/common/util/NEWDynamicMachine.kt b/src/main/java/github/kasuminova/novaeng/common/util/NEWDynamicMachine.kt new file mode 100644 index 00000000..92bd325a --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/util/NEWDynamicMachine.kt @@ -0,0 +1,5 @@ +package github.kasuminova.novaeng.common.util + +import hellfirepvp.modularmachinery.common.machine.DynamicMachine + +class NEWDynamicMachine(registryName: String) : DynamicMachine(registryName) \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/util/NEWMachineAssemblyManager.kt b/src/main/java/github/kasuminova/novaeng/common/util/NEWMachineAssemblyManager.kt new file mode 100644 index 00000000..1f2a722a --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/util/NEWMachineAssemblyManager.kt @@ -0,0 +1,340 @@ +package github.kasuminova.novaeng.common.util + +import appeng.api.AEApi +import appeng.api.config.Actionable +import appeng.api.networking.storage.IStorageGrid +import appeng.api.storage.IMEMonitor +import appeng.api.storage.channels.IFluidStorageChannel +import appeng.api.storage.channels.IItemStorageChannel +import appeng.api.storage.data.IAEFluidStack +import appeng.api.storage.data.IAEItemStack +import appeng.api.storage.data.IAEStack +import appeng.fluids.util.AEFluidStack +import appeng.me.helpers.PlayerSource +import appeng.util.item.AEItemStack +import com.circulation.random_complement.common.util.MEHandler +import com.glodblock.github.common.item.fake.FakeFluids +import hellfirepvp.modularmachinery.ModularMachinery +import hellfirepvp.modularmachinery.common.integration.ModIntegrationJEI +import hellfirepvp.modularmachinery.common.integration.preview.StructurePreviewWrapper +import hellfirepvp.modularmachinery.common.machine.DynamicMachine +import hellfirepvp.modularmachinery.common.network.PktAssemblyReport +import hellfirepvp.modularmachinery.common.util.BlockArray +import hellfirepvp.modularmachinery.common.util.ItemUtils +import ink.ikx.mmce.common.assembly.MachineAssembly +import ink.ikx.mmce.common.utils.StructureIngredient +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import it.unimi.dsi.fastutil.objects.ObjectIterator +import it.unimi.dsi.fastutil.objects.ObjectLists +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap +import it.unimi.dsi.fastutil.objects.ReferenceArrayList +import net.minecraft.block.Block +import net.minecraft.block.state.IBlockState +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.entity.player.EntityPlayerMP +import net.minecraft.item.ItemStack +import net.minecraft.util.Tuple +import net.minecraftforge.fluids.FluidStack +import java.util.stream.Collectors + +class NEWMachineAssemblyManager { + + data class BlockPair(val block: Block, val meta: Int) { + val blockState: IBlockState + get() : IBlockState { + @Suppress("DEPRECATION") + return block.getStateFromMeta(meta) + } + } + + companion object { + private val ADDITIONAL_CONSTRUCTORS by lazy { + Reference2ObjectOpenHashMap>() + } + private val MACHINE_ASSEMBLY_CACHE by lazy { + Object2ObjectOpenHashMap() + } + private val CheckAllItemComplete by lazy { + ObjectLists.singleton( + ObjectLists.singleton(ItemStack.EMPTY) + ) + } + private val emptyMiss2ListPair by lazy { + Miss2ListPair(0, ObjectLists.emptyList()) + } + + fun getAllDynamicMachines(): Collection { + val i = ObjectArrayList() + for (map in ADDITIONAL_CONSTRUCTORS.values) { + i.addAll(map.values) + } + return i + } + + fun getDynamicMachine(state: IBlockState): DynamicMachine? { + return getDynamicMachine(state.block, state.block.getMetaFromState(state)) + } + + fun getDynamicMachine(block: Block, meta: Int): DynamicMachine? { + return ADDITIONAL_CONSTRUCTORS[block]?.let { it[meta] } + } + + fun getConstructorsIterator(): ObjectIterator>> { + return ADDITIONAL_CONSTRUCTORS.entries.iterator() + } + + fun setConstructors(block: BlockPair, machine: NEWDynamicMachine) { + ADDITIONAL_CONSTRUCTORS.computeIfAbsent(block.block) { Int2ObjectOpenHashMap() }[block.meta] = machine + ModIntegrationJEI.PREVIEW_WRAPPERS.add(StructurePreviewWrapper(machine)) + } + + fun addAssemblyMachine(player: EntityPlayer, array: BlockArray): AssemblyBlockArray { + val newArray = AssemblyBlockArray(array) + MACHINE_ASSEMBLY_CACHE[player] = newArray + return newArray + } + + fun getMachineAssembly(player: EntityPlayer): AssemblyBlockArray? { + return MACHINE_ASSEMBLY_CACHE[player] + } + + fun checkMachineAssembly(player: EntityPlayer): Boolean { + return MACHINE_ASSEMBLY_CACHE.containsKey(player) + } + + fun removeMachineAssembly(player: EntityPlayer) { + MACHINE_ASSEMBLY_CACHE.remove(player)?.end() + } + + fun checkAllItems( + player: EntityPlayer, + ingredient: StructureIngredient, + usingAE: Boolean, + autoAECrafting: Boolean + ): Miss2ListPair { + if (player.isCreative) return emptyMiss2ListPair + val inventory = player.inventory.mainInventory.stream().map { obj: ItemStack -> obj.copy() } + .collect(Collectors.toCollection { ObjectArrayList() }) + val itemIngredientList = ingredient.itemIngredient() + val fluidIngredientList = ingredient.fluidIngredient() + MachineAssembly.searchAndRemoveContainItem(inventory, itemIngredientList) + MachineAssembly.searchAndRemoveContainFluid(inventory, fluidIngredientList) + if (itemIngredientList.isEmpty() && fluidIngredientList.isEmpty()) { + return emptyMiss2ListPair + } else { + val itemStackIngList = getItemStackIngList(itemIngredientList) + val fluidStackIngList = getFluidStackIngList(fluidIngredientList) + + if (usingAE) { + val obj = MEHandler.getTerminalGuiObject(player) + obj?.actionableNode?.grid?.let { + val storage = it.getCache(IStorageGrid::class.java) + val items: IMEMonitor = storage.getInventory( + AEApi.instance().storage().getStorageChannel(IItemStorageChannel::class.java) + ) + val fluids = storage.getInventory( + AEApi.instance().storage().getStorageChannel(IFluidStorageChannel::class.java) + ) + val playerSource = PlayerSource(player, obj) + for (stacks in ReferenceArrayList(itemStackIngList)) { + for (item in ReferenceArrayList(stacks)) { + val aeItem = items.extractItems( + AEItemStack.fromItemStack(item), + Actionable.SIMULATE, + playerSource + ) + if (aeItem == null) continue + val aeItemSize = aeItem.stackSize.toInt() + if (item.count <= aeItemSize) { + itemStackIngList.remove(stacks) + break + } else { + for (stack in stacks) { + stack.shrink(aeItemSize) + } + } + } + } + for (stacks in ReferenceArrayList(fluidStackIngList)) { + for (fluid in ReferenceArrayList(stacks)) { + val aeFluid = fluids.extractItems( + AEFluidStack.fromFluidStack(fluid), + Actionable.SIMULATE, + playerSource + ) + if (aeFluid == null) continue + val aeFluidSize = aeFluid.stackSize.toInt() + if (fluid.amount <= aeFluidSize) { + fluidStackIngList.remove(stacks) + break + } else { + for (stack in stacks) { + stack.amount -= aeFluidSize + } + } + } + } + } + if (itemStackIngList.isEmpty() && fluidStackIngList.isEmpty()) { + return emptyMiss2ListPair + } + } + + var miss = 0 + for (stacks in itemStackIngList) { + for (stack in stacks) { + miss += stack.count + break + } + } + for (stacks in fluidStackIngList) { + for (stack in stacks) { + miss += (stack.amount + 999) / 1000 + break + } + } + + val pkt = PktAssemblyReport(itemStackIngList, fluidStackIngList) + if (player is EntityPlayerMP) { + ModularMachinery.NET_CHANNEL.sendTo(pkt, player) + } + + return if (autoAECrafting) { + val list = ObjectArrayList(itemStackIngList) + for (stacks in fluidStackIngList) { + val fs = ObjectArrayList() + for (stack in stacks) { + val i = FakeFluids.packFluid2Drops(stack) + i.count = stack.amount + fs.add(i) + } + list.add(fs) + } + + Miss2ListPair(miss, list) + } else Miss2ListPair(miss, CheckAllItemComplete) + } + } + + class Miss2ListPair(val miss: Int, val list: List>) + + private fun getFluidStackIngList(fluidIngredientList: List): MutableList> { + val fluidStackIngList: MutableList> = ObjectArrayList() + + label36@ for (ingredient in fluidIngredientList) { + if (!ingredient.ingredientList().isEmpty()) { + val stackIngList = ingredient.ingredientList().stream() + .map { obj: Tuple -> obj.getFirst() } + .collect(Collectors.toCollection { ObjectArrayList() }) + if (stackIngList.size == 1) { + val ing = stackIngList[0] + + for (fluidStackList in fluidStackIngList) { + if (fluidStackList.size == 1) { + val another = fluidStackList[0] + if (ing.isFluidEqual(another)) { + another.amount += 1000 + continue@label36 + } + } + } + } + + fluidStackIngList.add(stackIngList) + } + } + + return fluidStackIngList + } + + private fun getItemStackIngList(itemIngredientList: List): MutableList> { + val stackList: MutableList> = ObjectArrayList() + + label56@ for (itemIng in itemIngredientList) { + if (!itemIng.ingredientList().isEmpty()) { + val stackIngList: MutableList = itemIng.ingredientList().stream() + .map { obj: Tuple -> obj.getFirst() } + .collect(Collectors.toCollection { ObjectArrayList() }) + if (stackIngList.size == 1) { + val ing = stackIngList[0] + + for (itemStackList in stackList) { + if (itemStackList.size == 1) { + val anotherInput = itemStackList[0] + if (ItemUtils.matchStacks(ing, anotherInput)) { + anotherInput.grow(1) + continue@label56 + } + } + } + } + + val filteredStackIngList: MutableList = ObjectArrayList() + + label44@ for (stack in stackIngList) { + for (filtered in filteredStackIngList) { + if (ItemUtils.matchStacks(stack, filtered)) { + continue@label44 + } + } + + filteredStackIngList.add(stack) + } + + stackList.add(filteredStackIngList) + } + } + + return stackList + } + } + + enum class OperatingStatus { + SUCCESS, + ALREADY_EXISTS, + FAILURE, + COMPLETE + } + + class Ingredient { + val ingredient: Any + val isItem: Boolean + val aeStack: IAEStack<*>? + + constructor(stack: ItemStack) { + this.ingredient = stack + this.isItem = true + this.aeStack = AEItemStack.fromItemStack(stack) + } + + constructor(stack: FluidStack) { + this.ingredient = stack + this.isItem = false + this.aeStack = AEFluidStack.fromFluidStack(stack) + } + + override fun equals(other: Any?): Boolean { + if (other == null || javaClass != other.javaClass) return false + val that = other as Ingredient + return isItem == that.isItem && aeStack == that.aeStack + } + + override fun hashCode(): Int { + return aeStack.hashCode() + } + + val itemStack: ItemStack + get() = ingredient as ItemStack + + val aEItemStack: IAEItemStack? + get() = aeStack as? IAEItemStack + + val fluidStack: FluidStack + get() = ingredient as FluidStack + + val aEFluidStack: IAEFluidStack? + get() = aeStack as? IAEFluidStack + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/common/util/TileItemHandler.java b/src/main/java/github/kasuminova/novaeng/common/util/TileItemHandler.java deleted file mode 100644 index c06c93b6..00000000 --- a/src/main/java/github/kasuminova/novaeng/common/util/TileItemHandler.java +++ /dev/null @@ -1,212 +0,0 @@ -package github.kasuminova.novaeng.common.util; - -import hellfirepvp.modularmachinery.common.tiles.base.TileEntitySynchronized; -import hellfirepvp.modularmachinery.common.util.IItemHandlerImpl; -import hellfirepvp.modularmachinery.common.util.ItemUtils; -import lombok.Getter; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTPrimitive; -import net.minecraft.nbt.NBTTagByte; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraftforge.common.util.Constants; - -import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.List; -import java.util.function.IntConsumer; -import java.util.stream.IntStream; - -public class TileItemHandler extends IItemHandlerImpl { - @Getter - protected final String invName; - protected final BitSet availableSlots = new BitSet(); - protected final TileEntitySynchronized owner; - - private IntConsumer onChangedListener = null; - - public TileItemHandler(final TileEntitySynchronized owner, final int[] inSlots, final int[] outSlots, final String invName) { - super(inSlots, outSlots); - this.owner = owner; - this.invName = invName; - } - - public static TileItemHandler create(final TileEntitySynchronized owner, final int slotCount, final String invName) { - int[] slotIDs = new int[slotCount]; - for (int slotID = 0; slotID < slotIDs.length; slotID++) { - slotIDs[slotID] = slotID; - } - return new TileItemHandler(owner, slotIDs, slotIDs, invName).setAllSlotAvailable().updateSlotLimits(); - } - - public TileItemHandler updateInOutSlots() { - int[] slotIDs = new int[inventory.length]; - for (int slotID = 0; slotID < slotIDs.length; slotID++) { - slotIDs[slotID] = slotID; - } - this.inSlots = slotIDs; - this.outSlots = slotIDs; - return this; - } - - public TileItemHandler updateSlotLimits() { - int[] slotLimits = new int[inventory.length]; - Arrays.fill(slotLimits, 1); - this.slotLimits = slotLimits; - return this; - } - - public TileItemHandler setOnChangedListener(final IntConsumer onChangedListener) { - this.onChangedListener = onChangedListener; - return this; - } - - public boolean isSlotAvailable(final int slotID) { - return availableSlots.get(slotID); - } - - public TileItemHandler setSlotAvailable(final int slotID) { - availableSlots.set(slotID); - return this; - } - - public TileItemHandler setAllSlotAvailable() { - availableSlots.set(0, inventory.length); - return this; - } - - public TileItemHandler setUnavailableSlots(final int[] slotIDs) { - for (final int slotID : slotIDs) { - availableSlots.set(slotID, false); - } - return this; - } - - public TileItemHandler setUnavailableSlot(final int slotID) { - availableSlots.set(slotID, false); - return this; - } - - public IntStream getAvailableSlotsStream() { - return availableSlots.stream(); - } - - @Override - public void setStackInSlot(int slot, @Nonnull ItemStack stack) { - super.setStackInSlot(slot, stack); - if (this.onChangedListener != null) { - this.onChangedListener.accept(slot); - } - if (this.owner != null) { - this.owner.markNoUpdateSync(); - } - } - - @Nonnull - public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { - if (stack.isEmpty()) { - return stack; - } - ItemStack inserted = this.insertItemInternal(slot, stack, simulate); - if (!simulate) { - if (this.onChangedListener != null) { - this.onChangedListener.accept(slot); - } - if (this.owner != null) { - this.owner.markNoUpdateSync(); - } - } - return inserted; - } - - @Nonnull - public ItemStack extractItem(int slot, int amount, boolean simulate) { - ItemStack extracted = super.extractItem(slot, amount, simulate); - if (!simulate) { - if (this.onChangedListener != null) { - this.onChangedListener.accept(slot); - } - if (this.owner != null) { - this.owner.markNoUpdateSync(); - } - } - return extracted; - } - - public NBTTagCompound writeNBT() { - List stackSet = new ArrayList<>(); - int[] stackSetIdxSet = new int[inventory.length]; - - invSet: - for (int i = 0; i < inventory.length; i++) { - SlotStackHolder holder = this.inventory[i]; - ItemStack stackInHolder = holder.itemStack.get(); - if (stackInHolder.isEmpty()) { - stackSetIdxSet[i] = -1; - continue; - } - - for (int stackSetIdx = 0; stackSetIdx < stackSet.size(); stackSetIdx++) { - ItemStack stackInSet = stackSet.get(stackSetIdx); - if (ItemUtils.matchStacks(stackInHolder, stackInSet)) { - stackSetIdxSet[i] = stackSetIdx; - continue invSet; - } - } - - stackSet.add(stackInHolder); - stackSetIdxSet[i] = stackSet.size() - 1; - } - - NBTTagList stackSetTag = new NBTTagList(); - NBTTagList invSetTag = new NBTTagList(); - - for (final ItemStack stack : stackSet) { - NBTTagCompound stackTag = stack.writeToNBT(new NBTTagCompound()); - if (stack.getCount() >= 127) { - stackTag.setInteger("Count", stack.getCount()); - } - stackSetTag.appendTag(stackTag); - } - for (final int setIdx : stackSetIdxSet) { - invSetTag.appendTag(new NBTTagByte((byte) setIdx)); - } - - NBTTagCompound tag = new NBTTagCompound(); - tag.setTag("stackSet", stackSetTag); - tag.setTag("invSet", invSetTag); - return tag; - } - - public void readNBT(NBTTagCompound tag) { - NBTTagList stackSetTag = tag.getTagList("stackSet", Constants.NBT.TAG_COMPOUND); - NBTTagList invSetTag = tag.getTagList("invSet", Constants.NBT.TAG_BYTE); - - List stackSet = new ArrayList<>(); - for (int i = 0; i < stackSetTag.tagCount(); i++) { - NBTTagCompound stackTag = stackSetTag.getCompoundTagAt(i); - ItemStack stack = new ItemStack(stackTag); - stack.setCount(stackTag.getInteger("Count")); - stackSet.add(stack); - } - - this.inventory = new SlotStackHolder[invSetTag.tagCount()]; - for (int i = 0; i < invSetTag.tagCount(); i++) { - SlotStackHolder holder = new SlotStackHolder(i); - int setIdx = ((NBTPrimitive) invSetTag.get(i)).getByte(); - if (setIdx != -1) { - holder.itemStack.set(stackSet.get(setIdx).copy()); - } - this.inventory[i] = holder; - } - - updateInOutSlots(); - updateSlotLimits(); - - if (onChangedListener != null) { - onChangedListener.accept(-1); - } - } -} diff --git a/src/main/java/github/kasuminova/novaeng/common/util/TileItemHandler.kt b/src/main/java/github/kasuminova/novaeng/common/util/TileItemHandler.kt new file mode 100644 index 00000000..ef7c8495 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/common/util/TileItemHandler.kt @@ -0,0 +1,199 @@ +package github.kasuminova.novaeng.common.util + +import hellfirepvp.modularmachinery.common.tiles.base.TileEntitySynchronized +import hellfirepvp.modularmachinery.common.util.IItemHandlerImpl +import hellfirepvp.modularmachinery.common.util.ItemUtils +import java.util.Arrays +import java.util.BitSet +import java.util.function.IntConsumer +import java.util.stream.IntStream +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTPrimitive +import net.minecraft.nbt.NBTTagByte +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.nbt.NBTTagList +import net.minecraftforge.common.util.Constants +import javax.annotation.Nonnull + +open class TileItemHandler( + val owner: TileEntitySynchronized, + inSlots: IntArray, + outSlots: IntArray, + val invName: String +) : IItemHandlerImpl(inSlots, outSlots) { + + companion object { + @JvmStatic + fun create(owner: TileEntitySynchronized, slotCount: Int, invName: String): TileItemHandler { + val slotIDs = IntArray(slotCount) + for (slotID in slotIDs.indices) { + slotIDs[slotID] = slotID + } + return TileItemHandler(owner, slotIDs, slotIDs, invName).setAllSlotAvailable().updateSlotLimits() + } + } + + protected val availableSlots: BitSet = BitSet() + + private var onChangedListener: IntConsumer? = null + + fun updateInOutSlots(): TileItemHandler { + val slotIDs = IntArray(inventory.size) + for (slotID in slotIDs.indices) { + slotIDs[slotID] = slotID + } + this.inSlots = slotIDs + this.outSlots = slotIDs + return this + } + + fun updateSlotLimits(): TileItemHandler { + val slotLimits = IntArray(inventory.size) + Arrays.fill(slotLimits, 1) + this.slotLimits = slotLimits + return this + } + + fun setOnChangedListener(onChangedListener: IntConsumer?): TileItemHandler { + this.onChangedListener = onChangedListener + return this + } + + fun isSlotAvailable(slotID: Int): Boolean { + return availableSlots.get(slotID) + } + + fun setSlotAvailable(slotID: Int): TileItemHandler { + availableSlots.set(slotID) + return this + } + + fun setAllSlotAvailable(): TileItemHandler { + availableSlots.set(0, inventory.size) + return this + } + + fun setUnavailableSlots(slotIDs: IntArray): TileItemHandler { + for (slotID in slotIDs) { + availableSlots.set(slotID, false) + } + return this + } + + fun setUnavailableSlot(slotID: Int): TileItemHandler { + availableSlots.set(slotID, false) + return this + } + + val availableSlotsStream: IntStream + get() = availableSlots.stream() + + override fun setStackInSlot(slot: Int, @Nonnull stack: ItemStack) { + super.setStackInSlot(slot, stack) + if (this.onChangedListener != null) { + this.onChangedListener!!.accept(slot) + } + this.owner.markNoUpdateSync() + } + + @Nonnull + override fun insertItem(slot: Int, @Nonnull stack: ItemStack, simulate: Boolean): ItemStack { + if (stack.isEmpty) { + return stack + } + val inserted = this.insertItemInternal(slot, stack, simulate) + if (!simulate) { + if (this.onChangedListener != null) { + this.onChangedListener!!.accept(slot) + } + this.owner.markNoUpdateSync() + } + return inserted + } + + @Nonnull + override fun extractItem(slot: Int, amount: Int, simulate: Boolean): ItemStack { + val extracted = super.extractItem(slot, amount, simulate) + if (!simulate) { + if (this.onChangedListener != null) { + this.onChangedListener!!.accept(slot) + } + this.owner.markNoUpdateSync() + } + return extracted + } + + fun writeNBT(): NBTTagCompound { + val stackSet = ArrayList() + val stackSetIdxSet = IntArray(inventory.size) + + invSet@ for (i in inventory.indices) { + val holder = this.inventory[i] + val stackInHolder = holder.itemStack.get() + if (stackInHolder.isEmpty) { + stackSetIdxSet[i] = -1 + continue + } + + for (stackSetIdx in stackSet.indices) { + val stackInSet = stackSet[stackSetIdx] + if (ItemUtils.matchStacks(stackInHolder, stackInSet)) { + stackSetIdxSet[i] = stackSetIdx + continue@invSet + } + } + + stackSet.add(stackInHolder) + stackSetIdxSet[i] = stackSet.size - 1 + } + + val stackSetTag = NBTTagList() + val invSetTag = NBTTagList() + + for (stack in stackSet) { + val stackTag = stack.writeToNBT(NBTTagCompound()) + if (stack.count >= 127) { + stackTag.setInteger("Count", stack.count) + } + stackSetTag.appendTag(stackTag) + } + for (setIdx in stackSetIdxSet) { + invSetTag.appendTag(NBTTagByte(setIdx.toByte())) + } + + val tag = NBTTagCompound() + tag.setTag("stackSet", stackSetTag) + tag.setTag("invSet", invSetTag) + return tag + } + + fun readNBT(tag: NBTTagCompound) { + val stackSetTag = tag.getTagList("stackSet", Constants.NBT.TAG_COMPOUND) + val invSetTag = tag.getTagList("invSet", Constants.NBT.TAG_BYTE) + + val stackSet = ArrayList() + for (i in 0..(invSetTag.tagCount()) + for (i in 0.. n$getCpus(); +} diff --git a/src/main/java/github/kasuminova/novaeng/mixin/ae2/AccessorCraftingCPURecord.java b/src/main/java/github/kasuminova/novaeng/mixin/ae2/AccessorCraftingCPURecord.java new file mode 100644 index 00000000..e1a09dea --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/ae2/AccessorCraftingCPURecord.java @@ -0,0 +1,13 @@ +package github.kasuminova.novaeng.mixin.ae2; + +import appeng.api.networking.crafting.ICraftingCPU; +import appeng.container.implementations.CraftingCPURecord; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(value = CraftingCPURecord.class, remap = false) +public interface AccessorCraftingCPURecord { + + @Accessor("cpu") + ICraftingCPU n$getCpu(); +} diff --git a/src/main/java/github/kasuminova/novaeng/mixin/ae2/AccessorGuiCraftConfirm.java b/src/main/java/github/kasuminova/novaeng/mixin/ae2/AccessorGuiCraftConfirm.java new file mode 100644 index 00000000..09925d9f --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/ae2/AccessorGuiCraftConfirm.java @@ -0,0 +1,16 @@ +package github.kasuminova.novaeng.mixin.ae2; + +import appeng.client.gui.implementations.GuiCraftConfirm; +import net.minecraft.client.gui.GuiButton; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(value = GuiCraftConfirm.class, remap = false) +public interface AccessorGuiCraftConfirm { + + @Accessor("cancel") + GuiButton n$getCancel(); + + @Accessor("start") + GuiButton n$getStart(); +} diff --git a/src/main/java/github/kasuminova/novaeng/mixin/minecraft/MixinGuiScreen.java b/src/main/java/github/kasuminova/novaeng/mixin/minecraft/MixinGuiScreen.java new file mode 100644 index 00000000..7ffca89c --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/minecraft/MixinGuiScreen.java @@ -0,0 +1,20 @@ +package github.kasuminova.novaeng.mixin.minecraft; + +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.ITextComponent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(GuiScreen.class) +public class MixinGuiScreen { + + @Inject(method = "handleComponentHover", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiScreen;renderToolTip(Lnet/minecraft/item/ItemStack;II)V")) + protected void handleComponentHover(ITextComponent component, int x, int y, CallbackInfo ci, @Local(ordinal = 0) ItemStack itemstack) { + Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemstack, x - 18, y); + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/mixin/mmce/AccessorAbstractMachine.java b/src/main/java/github/kasuminova/novaeng/mixin/mmce/AccessorAbstractMachine.java new file mode 100644 index 00000000..e7d16adb --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/mmce/AccessorAbstractMachine.java @@ -0,0 +1,15 @@ +package github.kasuminova.novaeng.mixin.mmce; + +import hellfirepvp.modularmachinery.common.machine.AbstractMachine; +import net.minecraft.util.ResourceLocation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(value = AbstractMachine.class, remap = false) +public interface AccessorAbstractMachine { + + @Accessor("registryName") + @Mutable + void setRL(ResourceLocation newRl); +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinBlockArrayCache.java b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinBlockArrayCache.java new file mode 100644 index 00000000..ed5472a4 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinBlockArrayCache.java @@ -0,0 +1,52 @@ +package github.kasuminova.novaeng.mixin.mmce; + +import github.kasuminova.mmce.common.util.DynamicPattern; +import github.kasuminova.novaeng.common.util.NEWMachineAssemblyManager; +import hellfirepvp.modularmachinery.common.machine.DynamicMachine; +import hellfirepvp.modularmachinery.common.machine.TaggedPositionBlockArray; +import hellfirepvp.modularmachinery.common.modifier.MultiBlockModifierReplacement; +import hellfirepvp.modularmachinery.common.util.BlockArray; +import hellfirepvp.modularmachinery.common.util.BlockArrayCache; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Collection; +import java.util.List; + +@Mixin(value = BlockArrayCache.class, remap = false) +public abstract class MixinBlockArrayCache { + + @Shadow + private static void buildBlockArrayCache(BlockArray blockArray) { + } + + @Shadow + private static void buildMultiBlockModifierCache(List replacementList) { + } + + @Shadow + private static void buildDynamicPatternCache(TaggedPositionBlockArray blockArray) { + } + + @Inject(method = "buildCache", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;forEach(Ljava/util/function/Consumer;)V", shift = At.Shift.AFTER)) + private static void buildCache(Collection machines, CallbackInfo ci) { + NEWMachineAssemblyManager.Companion.getAllDynamicMachines().parallelStream().forEach(machine -> { + TaggedPositionBlockArray blockArray = machine.getPattern(); + buildBlockArrayCache(blockArray); + buildMultiBlockModifierCache(machine.getMultiBlockModifiers()); + + for (DynamicPattern pattern : machine.getDynamicPatterns().values()) { + buildDynamicPatternCache(pattern.getPattern()); + TaggedPositionBlockArray patternEnd = pattern.getPatternEnd(); + if (patternEnd != null) { + buildDynamicPatternCache(patternEnd); + } + } + + }); + } + +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinBlockArrayPreviewRenderHelper.java b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinBlockArrayPreviewRenderHelper.java new file mode 100644 index 00000000..3718dd1b --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinBlockArrayPreviewRenderHelper.java @@ -0,0 +1,126 @@ +package github.kasuminova.novaeng.mixin.mmce; + +import github.kasuminova.novaeng.client.util.NEWBlockArrayPreviewRenderHelper; +import github.kasuminova.novaeng.mixin.util.BlockArrayPreviewRenderUtils; +import github.kasuminova.novaeng.mixin.util.BlockArrayRenderUtils; +import hellfirepvp.modularmachinery.client.util.BlockArrayPreviewRenderHelper; +import hellfirepvp.modularmachinery.client.util.BlockArrayRenderHelper; +import hellfirepvp.modularmachinery.common.block.BlockController; +import hellfirepvp.modularmachinery.common.util.BlockArray; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3i; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = BlockArrayPreviewRenderHelper.class, remap = false) +public abstract class MixinBlockArrayPreviewRenderHelper implements BlockArrayPreviewRenderUtils { + + @Shadow + @Setter + @Getter + private BlockPos attachedPosition; + + @Shadow + @Getter + @Setter + private int renderedLayer; + + @Shadow + @Getter + @Setter + private BlockArrayRenderHelper renderHelper; + @Shadow + @Getter + @Setter + private BlockArray matchArray; + @Shadow + @Getter + @Setter + private Vec3i renderHelperOffset; + @Unique + private EnumFacing n$facing; + + @Shadow + abstract void renderTranslucentBlocks(); + + @Shadow + protected abstract void updateLayers(); + + @Redirect(method = {"hashBlocks", "hasLowerLayer", "updateLayers"}, at = @At(value = "FIELD", target = "Lhellfirepvp/modularmachinery/client/util/BlockArrayPreviewRenderHelper;attachedPosition:Lnet/minecraft/util/math/BlockPos;")) + public BlockPos isRenderingComplete(BlockArrayPreviewRenderHelper instance) { + if (this.renderHelper == null) return this.attachedPosition; + if ((Object) this instanceof NEWBlockArrayPreviewRenderHelper) { + var maxY = ((BlockArrayRenderUtils) this.renderHelper).n$getBlocks().getMax().getY(); + if (renderedLayer > maxY) { + return null; + } + } + return this.attachedPosition; + } + + @Redirect(method = "batchBlocks", at = @At(value = "FIELD", target = "Lhellfirepvp/modularmachinery/client/util/BlockArrayPreviewRenderHelper;attachedPosition:Lnet/minecraft/util/math/BlockPos;", ordinal = 1)) + public BlockPos isRenderingCompleteB(BlockArrayPreviewRenderHelper instance) { + if (this.renderHelper == null) return this.attachedPosition; + if ((Object) this instanceof NEWBlockArrayPreviewRenderHelper) { + var maxY = ((BlockArrayRenderUtils) this.renderHelper).n$getBlocks().getMax().getY(); + if (renderedLayer > maxY) { + return null; + } + } + return this.attachedPosition; + } + + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lhellfirepvp/modularmachinery/client/util/BlockArrayPreviewRenderHelper;updateLayers()V")) + private void updateLayers(BlockArrayPreviewRenderHelper instance) { + if (!((Object) this == NEWBlockArrayPreviewRenderHelper.INSTANCE)) { + this.updateLayers(); + } + } + + @Unique + public void n$renderTranslucentBlocks() { + this.renderTranslucentBlocks(); + } + + @Inject(method = "clearSelection", at = @At("TAIL")) + public void onClear(CallbackInfo ci) { + if ((Object) this == NEWBlockArrayPreviewRenderHelper.INSTANCE) { + NEWBlockArrayPreviewRenderHelper.INSTANCE.clear(); + n$facing = null; + } + } + + @Redirect(method = "batchBlocks", at = @At(value = "CONSTANT", args = "classValue=hellfirepvp/modularmachinery/common/block/BlockController")) + public boolean isFacing(Object instance, Class type) { + return n$facing != null || instance instanceof BlockController; + } + + @Redirect(method = "batchBlocks", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/state/IBlockState;getValue(Lnet/minecraft/block/properties/IProperty;)Ljava/lang/Comparable;", remap = true)) + public > T setBlockFacing(IBlockState instance, IProperty tiProperty) { + if (n$facing != null && tiProperty == BlockController.FACING) { + return (T) n$facing; + } + return instance.getValue(tiProperty); + } + + @Intrinsic + public EnumFacing getFacing() { + return n$facing; + } + + @Intrinsic + public void setFacing(EnumFacing facing) { + n$facing = facing; + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinBlockArrayRenderHelper.java b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinBlockArrayRenderHelper.java new file mode 100644 index 00000000..266c4130 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinBlockArrayRenderHelper.java @@ -0,0 +1,22 @@ +package github.kasuminova.novaeng.mixin.mmce; + +import github.kasuminova.novaeng.mixin.util.BlockArrayRenderUtils; +import hellfirepvp.modularmachinery.client.util.BlockArrayRenderHelper; +import hellfirepvp.modularmachinery.common.util.BlockArray; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(value = BlockArrayRenderHelper.class, remap = false) +public class MixinBlockArrayRenderHelper implements BlockArrayRenderUtils { + + @Final + @Shadow + private BlockArray blocks; + + @Intrinsic + public BlockArray n$getBlocks() { + return blocks; + } +} diff --git a/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinDynamicMachineRenderContext.java b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinDynamicMachineRenderContext.java new file mode 100644 index 00000000..90812070 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinDynamicMachineRenderContext.java @@ -0,0 +1,23 @@ +package github.kasuminova.novaeng.mixin.mmce; + +import github.kasuminova.novaeng.common.util.NEWDynamicMachine; +import hellfirepvp.modularmachinery.client.util.DynamicMachineRenderContext; +import hellfirepvp.modularmachinery.common.machine.DynamicMachine; +import hellfirepvp.modularmachinery.common.util.BlockArray; +import net.minecraft.util.math.Vec3i; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = DynamicMachineRenderContext.class, remap = false) +public class MixinDynamicMachineRenderContext { + + @Inject(method = "addControllerToBlockArray", at = @At("HEAD"), cancellable = true) + private static void addControllerToBlockArray(DynamicMachine machine, BlockArray copy, Vec3i moveOffset, CallbackInfo ci) { + if (machine instanceof NEWDynamicMachine n) { + ci.cancel(); + } + } + +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinMEPatternProvider.java b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinMEPatternProvider.java index 3b39b48b..03fac60e 100644 --- a/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinMEPatternProvider.java +++ b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinMEPatternProvider.java @@ -22,4 +22,4 @@ public abstract class MixinMEPatternProvider extends MEMachineComponent implemen public void r$IgnoreParallel() { novaEngineering_Core$ignoreParallel = true; } -} +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinRecipeAdapterBuilder.java b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinRecipeAdapterBuilder.java index 90b5a92d..922a396a 100644 --- a/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinRecipeAdapterBuilder.java +++ b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinRecipeAdapterBuilder.java @@ -38,4 +38,4 @@ public class MixinRecipeAdapterBuilder implements NovaRAB { return novaEngineering_Core$outTags; } -} +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinWorldSceneRendererWidget.java b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinWorldSceneRendererWidget.java new file mode 100644 index 00000000..0a2108c2 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/mmce/MixinWorldSceneRendererWidget.java @@ -0,0 +1,25 @@ +package github.kasuminova.novaeng.mixin.mmce; + +import github.kasuminova.mmce.client.gui.widget.impl.preview.WorldSceneRendererWidget; +import github.kasuminova.novaeng.common.util.NEWDynamicMachine; +import hellfirepvp.modularmachinery.common.machine.DynamicMachine; +import hellfirepvp.modularmachinery.common.util.BlockArray; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = WorldSceneRendererWidget.class, remap = false) +public class MixinWorldSceneRendererWidget { + + @Shadow + protected BlockArray pattern; + + @Inject(method = "addControllerToPattern", at = @At("HEAD"), cancellable = true) + protected void addControllerToPattern(DynamicMachine machine, CallbackInfo ci) { + if (machine instanceof NEWDynamicMachine n) { + ci.cancel(); + } + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/novaeng/mixin/psi/MixinPieceTrickExplode.java b/src/main/java/github/kasuminova/novaeng/mixin/psi/MixinPieceTrickExplode.java index a27dd686..41832dd3 100644 --- a/src/main/java/github/kasuminova/novaeng/mixin/psi/MixinPieceTrickExplode.java +++ b/src/main/java/github/kasuminova/novaeng/mixin/psi/MixinPieceTrickExplode.java @@ -1,7 +1,7 @@ package github.kasuminova.novaeng.mixin.psi; -import github.kasuminova.novaeng.NovaEngineeringCore; import github.kasuminova.novaeng.NovaEngCoreConfig; +import github.kasuminova.novaeng.NovaEngineeringCore; import net.minecraft.util.text.TextComponentString; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; diff --git a/src/main/java/github/kasuminova/novaeng/mixin/util/BlockArrayPreviewRenderUtils.java b/src/main/java/github/kasuminova/novaeng/mixin/util/BlockArrayPreviewRenderUtils.java new file mode 100644 index 00000000..2b0c2efe --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/util/BlockArrayPreviewRenderUtils.java @@ -0,0 +1,36 @@ +package github.kasuminova.novaeng.mixin.util; + +import hellfirepvp.modularmachinery.client.util.BlockArrayRenderHelper; +import hellfirepvp.modularmachinery.common.util.BlockArray; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3i; + +public interface BlockArrayPreviewRenderUtils { + + BlockPos getAttachedPosition(); + + void setAttachedPosition(BlockPos pos); + + int getRenderedLayer(); + + void setRenderedLayer(int layer); + + BlockArrayRenderHelper getRenderHelper(); + + void setRenderHelper(BlockArrayRenderHelper renderHelper); + + void n$renderTranslucentBlocks(); + + BlockArray getMatchArray(); + + void setMatchArray(BlockArray matchArray); + + Vec3i getRenderHelperOffset(); + + void setRenderHelperOffset(Vec3i renderHelperOffset); + + EnumFacing getFacing(); + + void setFacing(EnumFacing facing); +} diff --git a/src/main/java/github/kasuminova/novaeng/mixin/util/BlockArrayRenderUtils.java b/src/main/java/github/kasuminova/novaeng/mixin/util/BlockArrayRenderUtils.java new file mode 100644 index 00000000..7b0c75d0 --- /dev/null +++ b/src/main/java/github/kasuminova/novaeng/mixin/util/BlockArrayRenderUtils.java @@ -0,0 +1,7 @@ +package github.kasuminova.novaeng.mixin.util; + +import hellfirepvp.modularmachinery.common.util.BlockArray; + +public interface BlockArrayRenderUtils { + BlockArray n$getBlocks(); +} \ No newline at end of file diff --git a/src/main/resources/assets/novaeng_core/lang/en_US.lang b/src/main/resources/assets/novaeng_core/lang/en_US.lang index 7d67bb01..23057b91 100644 --- a/src/main/resources/assets/novaeng_core/lang/en_US.lang +++ b/src/main/resources/assets/novaeng_core/lang/en_US.lang @@ -18,6 +18,36 @@ item.hypernet_connect_card.tooltip.no_pos.tip.1=§2右击任意等级的计算 item.hypernet_connect_card.tooltip.pos.tip.0=§b存储卡中保存的坐标:§a(X: %s, Y: %s, Z: %s) item.hypernet_connect_card.tooltip.pos.tip.1=§2右击任意等级的计算网络中心控制器来覆写数据。 +item.novaeng_core.machine_assembly_tool.name=§9高级结构构造器 + +message.assembly.tip.already_assembly.start=模块化组装:机器开始组装 +message.assembly.tip.fail=模块化组装: 在 %s 放置方块失败,已返还材料 + +gui.blueprint.popout.placed.dynamic_pattern.unload=当前结构预览已结束 + +tile.Reactor.name=Fusion Reactor +tile.ThermalEvaporation.name=Thermal Evaporation Tower + +config.field.UsingAE.entry=使用AE +text.machine_assembly_tool.config.UsingAE=允许使用背包内可用的第一个无线终端链接的网络内物品工作(支持饰品栏) +config.field.IgnoreFluids.entry=忽略流体 +text.machine_assembly_tool.config.IgnoreFluids=是否在目标搭建位置为流体时继续搭建 +config.field.DynamicPatternSize.entry=动态结构层数 +text.machine_assembly_tool.config.DynamicPatternSize=搭建动态结构时所搭建的层数 +config.field.AutoAECrafting.entry=自动AE合成 +text.machine_assembly_tool.config.AutoAECrafting=在允许使用AE时,将会尝试请求可合成的缺失的材料的合成 +config.field.NeedAllIngredient.entry=完整材料需求 +text.machine_assembly_tool.config.NeedAllIngredient=是否需要有结构所需的所有材料时才开始搭建 + +item.novaeng_core.machine_assembly_tool.tooltip.0=右键机械控制器以进行投影 +item.novaeng_core.machine_assembly_tool.tooltip.1=在潜行状态下使用滚轮切换投影层数 +item.novaeng_core.machine_assembly_tool.tooltip.2=潜行右键机械控制器以触发自动搭建 +item.novaeng_core.machine_assembly_tool.tooltip.3=右键空气打开配置GUI +item.novaeng_core.machine_assembly_tool.config=当前状态: + +tooltip.machine_assembly_tool.0=§r作为 §6%s§r 的主方块 +tooltip.machine_assembly_tool.1=§r可使用 §6%s§r 投影或自动搭建 + item.novaeng_core.estorage_cell_item_16m.name=§9ECO - §bSE4 §9存储矩阵§a(物品) item.novaeng_core.estorage_cell_item_64m.name=§9ECO - §6SE6 §9存储矩阵§a(物品) item.novaeng_core.estorage_cell_item_256m.name=§9ECO - §5SE9 §9存储矩阵§a(物品) @@ -943,6 +973,7 @@ new.ctrl.tooltip.help=§9//////// 控制器提示 ///////// new.ctrl.tooltip.base=§9§o每个机械的独立控制器,JEI 中左键以查看结构 new.ctrl.tooltip.factory=§9§o控制器的工厂变种,包含特殊功能 new.ctrl.tooltip.structure=§9§oJEI 中左键以查看结构 +new.ctrl.tooltip.assembly=§9使用 %s 或 %s 自动搭建结构 new.energy.storge=§a能量缓存: %s new.energy.max_input=§a最大输入: %s diff --git a/src/main/resources/assets/novaeng_core/lang/zh_CN.lang b/src/main/resources/assets/novaeng_core/lang/zh_CN.lang index 5d7974cc..d3c4612d 100644 --- a/src/main/resources/assets/novaeng_core/lang/zh_CN.lang +++ b/src/main/resources/assets/novaeng_core/lang/zh_CN.lang @@ -18,6 +18,36 @@ item.hypernet_connect_card.tooltip.no_pos.tip.1=§2右击任意等级的计算 item.hypernet_connect_card.tooltip.pos.tip.0=§b存储卡中保存的坐标:§a(X: %s, Y: %s, Z: %s) item.hypernet_connect_card.tooltip.pos.tip.1=§2右击任意等级的计算网络中心控制器来覆写数据。 +item.novaeng_core.machine_assembly_tool.name=§9高级结构构造器 + +message.assembly.tip.already_assembly.start=模块化组装:机器开始组装 +message.assembly.tip.fail=模块化组装: 在 %s 放置方块失败,已返还材料 + +gui.blueprint.popout.placed.dynamic_pattern.unload=当前结构预览已结束 + +tile.Reactor.name=聚变反应堆 +tile.ThermalEvaporation.name=热力蒸馏塔 + +config.field.UsingAE.entry=使用AE +text.machine_assembly_tool.config.UsingAE=允许使用背包内可用的第一个无线终端链接的网络内物品工作(支持饰品栏) +config.field.IgnoreFluids.entry=忽略流体 +text.machine_assembly_tool.config.IgnoreFluids=是否在目标搭建位置为流体时继续搭建 +config.field.DynamicPatternSize.entry=动态结构层数 +text.machine_assembly_tool.config.DynamicPatternSize=搭建动态结构时所搭建的层数 +config.field.AutoAECrafting.entry=自动AE合成 +text.machine_assembly_tool.config.AutoAECrafting=在允许使用AE时,将会尝试请求可合成的缺失的材料的合成 +config.field.NeedAllIngredient.entry=完整材料需求 +text.machine_assembly_tool.config.NeedAllIngredient=是否需要有结构所需的所有材料时才开始搭建 + +item.novaeng_core.machine_assembly_tool.tooltip.0=右键机械控制器以进行投影 +item.novaeng_core.machine_assembly_tool.tooltip.1=在潜行状态下使用滚轮切换投影层数 +item.novaeng_core.machine_assembly_tool.tooltip.2=潜行右键机械控制器以触发自动搭建 +item.novaeng_core.machine_assembly_tool.tooltip.3=右键空气打开配置GUI +item.novaeng_core.machine_assembly_tool.config=当前状态: + +tooltip.machine_assembly_tool.0=§r作为 §6%s§r 的主方块 +tooltip.machine_assembly_tool.1=§r可使用 §6%s§r 投影或自动搭建 + item.novaeng_core.estorage_cell_item_16m.name=§9ECO - §bSE4 §9存储矩阵§a(物品) item.novaeng_core.estorage_cell_item_64m.name=§9ECO - §6SE6 §9存储矩阵§a(物品) item.novaeng_core.estorage_cell_item_256m.name=§9ECO - §5SE9 §9存储矩阵§a(物品) @@ -943,6 +973,7 @@ new.ctrl.tooltip.help=§9//////// 控制器提示 ///////// new.ctrl.tooltip.base=§9§o每个机械的独立控制器,JEI 中左键以查看结构 new.ctrl.tooltip.factory=§9§o控制器的工厂变种,包含特殊功能 new.ctrl.tooltip.structure=§9§oJEI 中左键以查看结构 +new.ctrl.tooltip.assembly=§9使用 %s 或 %s 自动搭建结构 new.energy.storge=§a能量缓存: %s new.energy.max_input=§a最大输入: %s diff --git a/src/main/resources/assets/novaeng_core/models/item/machine_assembly_tool.json b/src/main/resources/assets/novaeng_core/models/item/machine_assembly_tool.json new file mode 100644 index 00000000..587053f1 --- /dev/null +++ b/src/main/resources/assets/novaeng_core/models/item/machine_assembly_tool.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "novaeng_core:items/machine_assembly_tool" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/novaeng_core/textures/items/machine_assembly_tool.png b/src/main/resources/assets/novaeng_core/textures/items/machine_assembly_tool.png new file mode 100644 index 00000000..7ea0aa84 Binary files /dev/null and b/src/main/resources/assets/novaeng_core/textures/items/machine_assembly_tool.png differ diff --git a/src/main/resources/assets/novaeng_core/textures/items/machine_assembly_tool_e.png b/src/main/resources/assets/novaeng_core/textures/items/machine_assembly_tool_e.png new file mode 100644 index 00000000..6599b94b Binary files /dev/null and b/src/main/resources/assets/novaeng_core/textures/items/machine_assembly_tool_e.png differ diff --git a/src/main/resources/mixins.novaeng_core.json b/src/main/resources/mixins.novaeng_core.json index f1622296..15150299 100644 --- a/src/main/resources/mixins.novaeng_core.json +++ b/src/main/resources/mixins.novaeng_core.json @@ -8,12 +8,18 @@ "MixinIngredientItemStackRenderer" ], "mixins": [ + "AccessorAbstractMachine", + "MixinBlockArrayCache", + "MixinBlockArrayPreviewRenderHelper", + "MixinBlockArrayRenderHelper", "MixinCommonProxy", + "MixinDynamicMachineRenderContext", "MixinMachineRecipe", "MixinMachineRegistry", "MixinMEPatternProvider", "MixinRecipeAdapterBuilder", "MixinTaskExecutor", - "MixinTileMultiblockMachineController" + "MixinTileMultiblockMachineController", + "MixinWorldSceneRendererWidget" ] } \ No newline at end of file diff --git a/src/main/resources/mixins.novaeng_core_ae2.json b/src/main/resources/mixins.novaeng_core_ae2.json index 1f6abcc6..5ab98936 100644 --- a/src/main/resources/mixins.novaeng_core_ae2.json +++ b/src/main/resources/mixins.novaeng_core_ae2.json @@ -5,6 +5,7 @@ "minVersion": "0.8", "compatibilityLevel": "JAVA_8", "client": [ + "AccessorGuiCraftConfirm", "MixinAppEngClientPacketHandler", "MixinGuiCraftingStatus", "MixinGuiPatternTerm" @@ -15,7 +16,9 @@ "mixins": [ "AccessorAbstractCellInventory", "AccessorCellRegistry", + "AccessorContainerCraftConfirm", "AccessorContainerPatternEncoder", + "AccessorCraftingCPURecord", "MixinAppEngServerPacketHandler", "MixinCraftingCPUCluster", "MixinCraftingCPUClusterTwo", diff --git a/src/main/resources/mixins.novaeng_core_vanilla.json b/src/main/resources/mixins.novaeng_core_vanilla.json index cf8a96e3..2256f466 100644 --- a/src/main/resources/mixins.novaeng_core_vanilla.json +++ b/src/main/resources/mixins.novaeng_core_vanilla.json @@ -12,6 +12,7 @@ "client": [ "AccessorParticleManager", "MixinFontRenderer", + "MixinGuiScreen", "MixinNetHandlerPlayClient", "MixinNettyCompressionDecoder", "forge.MixinForgeHooksClient"