diff --git a/addon.gradle b/addon.gradle deleted file mode 100644 index a6a3649..0000000 --- a/addon.gradle +++ /dev/null @@ -1,18 +0,0 @@ -apply plugin: 'org.jetbrains.kotlin.jvm' -apply plugin: 'com.github.gmazzo.buildconfig' - -compileKotlin { - kotlinOptions { - jvmTarget = 1.8 - } -} - -buildConfig { - packageName(project.modGroup) - className('ModTags') - buildConfigField('String', 'MODID', "\"${project.modId}\"") - buildConfigField('String', 'MODNAME', "\"${project.modName}\"") - buildConfigField('String', 'VERSION', "\"${project.modVersion}\"") - buildConfigField('String', 'GROUPNAME', "\"${project.modGroup}\"") - useKotlinOutput { topLevelConstants = true } -} diff --git a/gradle.properties b/gradle.properties index 90aad3e..f5c0178 100644 --- a/gradle.properties +++ b/gradle.properties @@ -41,7 +41,7 @@ developmentEnvironmentUserName = Developer # Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8. # See https://github.com/bsideup/jabel for details on how this works. -enableModernJavaSyntax = false +enableModernJavaSyntax = true # Enables injecting missing generics into the decompiled source code for a better coding experience. # Turns most publicly visible List, Map, etc. into proper List, Map types. @@ -50,19 +50,19 @@ enableGenericInjection = false # Generate a class with a String field for the mod version named as defined below. # If generateGradleTokenClass is empty or not missing, no such class will be generated. # If gradleTokenVersion is empty or missing, the field will not be present in the class. -generateGradleTokenClass = +generateGradleTokenClass = com.muxiu1997.mxrandom.Tags # Name of the token containing the project's current version to generate/replace. -gradleTokenVersion = GRADLETOKEN_VERSION +gradleTokenVersion = VERSION # [DEPRECATED] Mod ID replacement token. -gradleTokenModId = GRADLETOKEN_MODID +gradleTokenModId = # [DEPRECATED] Mod name replacement token. -gradleTokenModName = GRADLETOKEN_MODNAME +gradleTokenModName = # [DEPRECATED] Mod Group replacement token. -gradleTokenGroupName = GRADLETOKEN_GROUPNAME +gradleTokenGroupName = # [DEPRECATED] # Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java @@ -70,7 +70,7 @@ gradleTokenGroupName = GRADLETOKEN_GROUPNAME # The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's # version in @Mod([...], version = VERSION, [...]). # Leave these properties empty to skip individual token replacements. -replaceGradleTokenInFile = Tags.java +replaceGradleTokenInFile = # In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can # leave this property empty. diff --git a/src/main/java/com/muxiu1997/mxrandom/MXRandom.java b/src/main/java/com/muxiu1997/mxrandom/MXRandom.java new file mode 100644 index 0000000..55ead61 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/MXRandom.java @@ -0,0 +1,40 @@ +package com.muxiu1997.mxrandom; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.muxiu1997.mxrandom.loader.GTMetaTileEntityLoader; +import com.muxiu1997.mxrandom.loader.NetworkLoader; +import com.muxiu1997.mxrandom.loader.RecipeLoader; + +import cpw.mods.fml.common.Mod; +import cpw.mods.fml.common.Mod.EventHandler; +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLPostInitializationEvent; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; + +@Mod( + modid = MXRandom.MODID, + name = MXRandom.MODNAME, + version = Tags.VERSION, + dependencies = "required-after:appliedenergistics2;" + "required-after:gregtech") +public class MXRandom { + + public static final String MODID = "mxrandom"; + public static final String MODNAME = "MX-Random"; + + public static Logger logger = LogManager.getLogger(MODID); + public static final SimpleNetworkWrapper network = NetworkRegistry.INSTANCE.newSimpleChannel(MODID); + + @EventHandler + public void onInit(FMLInitializationEvent event) { + GTMetaTileEntityLoader.load(); + NetworkLoader.load(); + } + + @EventHandler + public void onPostInit(FMLPostInitializationEvent event) { + RecipeLoader.load(); + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/Utils.java b/src/main/java/com/muxiu1997/mxrandom/Utils.java new file mode 100644 index 0000000..6e947cc --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/Utils.java @@ -0,0 +1,18 @@ +package com.muxiu1997.mxrandom; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; + +public class Utils { + + public static IMetaTileEntity getMetaTileEntity(World w, int x, int y, int z) { + TileEntity te = w.getTileEntity(x, y, z); + if (te instanceof IGregTechTileEntity igtte) { + return igtte.getMetaTileEntity(); + } + return null; + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/api/IConfigurableMetaTileEntity.java b/src/main/java/com/muxiu1997/mxrandom/api/IConfigurableMetaTileEntity.java new file mode 100644 index 0000000..7ce7b13 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/api/IConfigurableMetaTileEntity.java @@ -0,0 +1,38 @@ +package com.muxiu1997.mxrandom.api; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.common.util.ForgeDirection; + +import com.muxiu1997.mxrandom.MXRandom; +import com.muxiu1997.mxrandom.network.message.MessageSyncMetaTileEntityConfig; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import io.netty.buffer.ByteBuf; + +public interface IConfigurableMetaTileEntity { + + IGregTechTileEntity getBaseMetaTileEntity(); + + void readConfigFromBytes(ByteBuf buf); + + void writeConfigToBytes(ByteBuf buf); + + default void applyConfigChanges() { + IGregTechTileEntity te = getBaseMetaTileEntity(); + te.markDirty(); + if (te.isServerSide()) { + MXRandom.network.sendToServer(new MessageSyncMetaTileEntityConfig(this, false)); + } else if (te.isClientSide()) { + MXRandom.network.sendToAll(new MessageSyncMetaTileEntityConfig(this, false)); + } + } + + Object getServerGuiElement(int ID, EntityPlayer player); + + @SideOnly(Side.CLIENT) + Object getClientGuiElement(int ID, EntityPlayer player); + + void onScrewdriverRightClick(ForgeDirection side, EntityPlayer player, float x, float y, float z); +} diff --git a/src/main/java/com/muxiu1997/mxrandom/api/network/IMessageBothSideHandler.java b/src/main/java/com/muxiu1997/mxrandom/api/network/IMessageBothSideHandler.java new file mode 100644 index 0000000..33b0d72 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/api/network/IMessageBothSideHandler.java @@ -0,0 +1,20 @@ +package com.muxiu1997.mxrandom.api.network; + +import org.jetbrains.annotations.NotNull; + +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import cpw.mods.fml.relauncher.Side; + +public interface IMessageBothSideHandler + extends IMessageServerSideHandler, IMessageClientSideHandler { + + @Override + default REPLY onMessage(@NotNull REQ message, @NotNull MessageContext ctx) { + if (ctx.side == Side.SERVER) { + return handleServerSideMessage(message, ctx); + } else { + return handleClientSideMessage(message, ctx); + } + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/api/network/IMessageClientSideHandler.java b/src/main/java/com/muxiu1997/mxrandom/api/network/IMessageClientSideHandler.java new file mode 100644 index 0000000..14dcd36 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/api/network/IMessageClientSideHandler.java @@ -0,0 +1,22 @@ +package com.muxiu1997.mxrandom.api.network; + +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public interface IMessageClientSideHandler + extends IMessageHandler { + + @Override + default REPLY onMessage(REQ message, MessageContext ctx) { + if (ctx.side == Side.SERVER) { + throw new IllegalAccessError("Cannot handle server-side messages"); + } + return handleClientSideMessage(message, ctx); + } + + @SideOnly(Side.CLIENT) + REPLY handleClientSideMessage(REQ message, MessageContext ctx); +} diff --git a/src/main/java/com/muxiu1997/mxrandom/api/network/IMessageServerSideHandler.java b/src/main/java/com/muxiu1997/mxrandom/api/network/IMessageServerSideHandler.java new file mode 100644 index 0000000..b9e2475 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/api/network/IMessageServerSideHandler.java @@ -0,0 +1,20 @@ +package com.muxiu1997.mxrandom.api.network; + +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import cpw.mods.fml.relauncher.Side; + +public interface IMessageServerSideHandler + extends IMessageHandler { + + @Override + default REPLY onMessage(REQ message, MessageContext ctx) { + if (ctx.side == Side.CLIENT) { + throw new IllegalAccessError("Cannot handle client-side messages"); + } + return handleServerSideMessage(message, ctx); + } + + REPLY handleServerSideMessage(REQ message, MessageContext ctx); +} diff --git a/src/main/java/com/muxiu1997/mxrandom/client/fx/CraftingFX.java b/src/main/java/com/muxiu1997/mxrandom/client/fx/CraftingFX.java new file mode 100644 index 0000000..e408785 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/client/fx/CraftingFX.java @@ -0,0 +1,71 @@ +package com.muxiu1997.mxrandom.client.fx; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemBlock; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; + +import org.lwjgl.opengl.GL11; + +import appeng.api.storage.data.IAEItemStack; + +public class CraftingFX extends EntityFX { + + private final EntityItem entityItem; + private final boolean isItemBlock; + + public CraftingFX(World w, double x, double y, double z, int age, IAEItemStack itemStack) { + super(w, x, y, z, 0, 0, 0); + this.entityItem = new EntityItem(this.worldObj, 0, 0, 0, itemStack.getItemStack()); + this.entityItem.hoverStart = 0; + this.isItemBlock = itemStack.getItemStack().getItem() instanceof ItemBlock; + + this.motionX = 0; + this.motionY = 0; + this.motionZ = 0; + this.particleMaxAge = age + 1; + this.noClip = true; + } + + @Override + public void renderParticle(Tessellator tessellator, float renderPartialTicks, float rX, float rY, float rZ, + float rYZ, float rXY) { + Tessellator.instance.draw(); + GL11.glPushMatrix(); + + float ticks = Minecraft.getMinecraft().renderViewEntity.ticksExisted; + double x = (prevPosX + (posX - prevPosX) * renderPartialTicks - interpPosX); + double y = (prevPosY + (posY - prevPosY) * renderPartialTicks - interpPosY); + double z = (prevPosZ + (posZ - prevPosZ) * renderPartialTicks - interpPosZ); + float h = MathHelper.sin(ticks % 32767.0f / 16.0f) * 0.05f; + float scale = isItemBlock ? 3.6f : 1.8f; + + GL11.glTranslatef((float) x + 0.5f, (float) y + 0.15f + h, (float) z + 0.5f); + GL11.glRotatef(ticks % 360.0f, 0, 1, 0); + GL11.glScalef(scale, scale, scale); + + RenderManager.instance.renderEntityWithPosYaw(entityItem, 0, 0, 0, 0, 0); + + GL11.glPopMatrix(); + Tessellator.instance.startDrawingQuads(); + } + + @Override + public int getBrightnessForRender(float partialTickTime) { + return super.getBrightnessForRender((15 << 20) | (15 << 4)); + } + + @Override + public int getFXLayer() { + return isItemBlock ? 1 : 2; + } + + @Override + public boolean shouldRenderInPass(int pass) { + return pass == 2; + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/client/gui/GuiConfigLargeMolecularAssembler.java b/src/main/java/com/muxiu1997/mxrandom/client/gui/GuiConfigLargeMolecularAssembler.java new file mode 100644 index 0000000..3528036 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/client/gui/GuiConfigLargeMolecularAssembler.java @@ -0,0 +1,90 @@ +package com.muxiu1997.mxrandom.client.gui; + +import java.awt.Color; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; + +import com.muxiu1997.mxrandom.MXRandom; +import com.muxiu1997.mxrandom.metatileentity.MTELargeMolecularAssembler; +import com.muxiu1997.mxrandom.network.container.ContainerConfigLargeMolecularAssembler; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class GuiConfigLargeMolecularAssembler extends GuiContainer { + + private static final ResourceLocation BACKGROUND_TEXTURE = new ResourceLocation( + MXRandom.MODID, + "textures/gui/configMetaTileEntity.png"); + private static final String LANG_CRAFTING_FX = "mxrandom.client.gui.GuiConfigLargeMolecularAssembler.craftingFX"; + private static final String LANG_VISIBLE = "mxrandom.client.gui.GuiConfigLargeMolecularAssembler.visible"; + private static final String LANG_HIDDEN = "mxrandom.client.gui.GuiConfigLargeMolecularAssembler.hidden"; + + private static final int PADDING = 8; + private static final int BUTTON_WIDTH = 40; + private static final int BUTTON_HEIGHT = 18; + + private GuiButton buttonToggleCraftingFX; + private final MTELargeMolecularAssembler LMA; + + public GuiConfigLargeMolecularAssembler(ContainerConfigLargeMolecularAssembler container) { + super(container); + this.LMA = container.LMA; + this.xSize = 176; + this.ySize = 107; + } + + @Override + public void initGui() { + super.initGui(); + buttonToggleCraftingFX = new GuiButton( + 0, + guiLeft + xSize - BUTTON_WIDTH - PADDING, + guiTop + PADDING + 16, + BUTTON_WIDTH, + BUTTON_HEIGHT, + buttonToggleCraftingFXDisplayString()); + buttonList.add(buttonToggleCraftingFX); + } + + @Override + public void updateScreen() { + super.updateScreen(); + buttonToggleCraftingFX.displayString = buttonToggleCraftingFXDisplayString(); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { + this.mc.getTextureManager().bindTexture(BACKGROUND_TEXTURE); + drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize); + } + + @Override + protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { + fontRendererObj.drawString(LMA.getLocalName(), PADDING, PADDING, Color.BLACK.getRGB()); + fontRendererObj.drawString( + StatCollector.translateToLocal(LANG_CRAFTING_FX), + PADDING, + PADDING + 20, + Color.BLACK.getRGB()); + } + + @Override + protected void actionPerformed(GuiButton button) { + if (button == buttonToggleCraftingFX) { + LMA.hiddenCraftingFX = !LMA.hiddenCraftingFX; + LMA.applyConfigChanges(); + } + } + + private String buttonToggleCraftingFXDisplayString() { + if (LMA.hiddenCraftingFX) { + return StatCollector.translateToLocal(LANG_HIDDEN); + } + return StatCollector.translateToLocal(LANG_VISIBLE); + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/loader/GTMetaTileEntityLoader.java b/src/main/java/com/muxiu1997/mxrandom/loader/GTMetaTileEntityLoader.java new file mode 100644 index 0000000..d6b3dc6 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/loader/GTMetaTileEntityLoader.java @@ -0,0 +1,17 @@ +package com.muxiu1997.mxrandom.loader; + +import com.muxiu1997.mxrandom.metatileentity.MTELargeMolecularAssembler; + +public class GTMetaTileEntityLoader { + + public static final int MTE_ID_OFFSET = 14100; + + public static MTELargeMolecularAssembler largeMolecularAssembler; + + public static void load() { + largeMolecularAssembler = new MTELargeMolecularAssembler( + MTE_ID_OFFSET + 1, + "largemolecularassembler", + "Large Molecular Assembler"); + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/loader/NetworkLoader.java b/src/main/java/com/muxiu1997/mxrandom/loader/NetworkLoader.java new file mode 100644 index 0000000..e70c801 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/loader/NetworkLoader.java @@ -0,0 +1,28 @@ +package com.muxiu1997.mxrandom.loader; + +import com.muxiu1997.mxrandom.MXRandom; +import com.muxiu1997.mxrandom.network.GuiHandler; +import com.muxiu1997.mxrandom.network.message.MessageCraftingFX; +import com.muxiu1997.mxrandom.network.message.MessageSyncMetaTileEntityConfig; + +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.relauncher.Side; + +public class NetworkLoader { + + public static void load() { + MXRandom.network.registerMessage(new MessageCraftingFX.Handler(), MessageCraftingFX.class, 0, Side.CLIENT); + MXRandom.network.registerMessage( + new MessageSyncMetaTileEntityConfig.Handler(), + MessageSyncMetaTileEntityConfig.class, + 1, + Side.SERVER); + MXRandom.network.registerMessage( + new MessageSyncMetaTileEntityConfig.Handler(), + MessageSyncMetaTileEntityConfig.class, + 2, + Side.CLIENT); + + NetworkRegistry.INSTANCE.registerGuiHandler(MXRandom.MODID, new GuiHandler()); + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/loader/RecipeLoader.java b/src/main/java/com/muxiu1997/mxrandom/loader/RecipeLoader.java new file mode 100644 index 0000000..422c7f5 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/loader/RecipeLoader.java @@ -0,0 +1,6 @@ +package com.muxiu1997.mxrandom.loader; + +public class RecipeLoader { + + public static void load() {} +} diff --git a/src/main/java/com/muxiu1997/mxrandom/metatileentity/MTELargeMolecularAssembler.java b/src/main/java/com/muxiu1997/mxrandom/metatileentity/MTELargeMolecularAssembler.java new file mode 100644 index 0000000..5c38638 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/metatileentity/MTELargeMolecularAssembler.java @@ -0,0 +1,688 @@ +package com.muxiu1997.mxrandom.metatileentity; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.*; +import static gregtech.api.util.GTStructureUtility.ofHatchAdder; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.BiFunction; +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.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.common.util.ForgeDirection; + +import org.apache.commons.lang3.tuple.Pair; + +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.IStructureElementCheckOnly; +import com.gtnewhorizon.structurelib.structure.StructureDefinition; +import com.mojang.authlib.GameProfile; +import com.muxiu1997.mxrandom.MXRandom; +import com.muxiu1997.mxrandom.api.IConfigurableMetaTileEntity; +import com.muxiu1997.mxrandom.client.gui.GuiConfigLargeMolecularAssembler; +import com.muxiu1997.mxrandom.network.container.ContainerConfigLargeMolecularAssembler; +import com.muxiu1997.mxrandom.network.message.MessageCraftingFX; +import com.muxiu1997.mxrandom.network.message.MessageSyncMetaTileEntityConfig; + +import appeng.api.AEApi; +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.MENetworkCraftingPatternChange; +import appeng.api.networking.security.BaseActionSource; +import appeng.api.networking.security.IActionHost; +import appeng.api.networking.security.MachineSource; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.api.util.DimensionalCoord; +import appeng.core.worlddata.WorldData; +import appeng.items.misc.ItemEncodedPattern; +import appeng.me.GridAccessException; +import appeng.me.GridNode; +import appeng.me.helpers.AENetworkProxy; +import appeng.me.helpers.IGridProxyable; +import appeng.util.Platform; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.GregTechAPI; +import gregtech.api.enums.ItemList; +import gregtech.api.enums.Textures; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.metatileentity.BaseMetaTileEntity; +import gregtech.api.metatileentity.implementations.MTEExtendedPowerMultiBlockBase; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GTUtility; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.common.items.behaviors.BehaviourDataOrb; +import gregtech.common.tileentities.machines.MTEHatchCraftingInputME; +import io.netty.buffer.ByteBuf; + +public class MTELargeMolecularAssembler extends MTEExtendedPowerMultiBlockBase + implements IConfigurableMetaTileEntity, ICraftingProvider, IActionHost, IGridProxyable { + + private static final String DATA_ORB_JOBS_KEY = "MX-CraftingJobs"; + private static final String DATA_ORB_JOBS_JOB_KEY = "Job"; + private static final String MACHINE_TYPE = "Molecular Assembler"; + private static final int EU_PER_TICK_BASIC = 16; + private static final int EU_PER_TICK_CRAFTING = 64; + private static final int CASING_INDEX = 48; + private static final int MIN_CASING_COUNT = 24; + private static final String DATA_ORB_TITLE = "AE-JOBS"; + private static final String NBT_KEY_CACHED_OUTPUTS = "cachedOutputs"; + private static final String NBT_KEY_CONFIG_HIDDEN_CRAFTING_FX = "config:hiddenCraftingFX"; + private static final int STRUCTURE_HORIZONTAL_OFFSET = 2; + private static final int STRUCTURE_VERTICAL_OFFSET = 4; + private static final int STRUCTURE_DEPTH_OFFSET = 0; + private static final String STRUCTURE_PIECE_MAIN = "main"; + private static final IStructureDefinition STRUCTURE_DEFINITION = StructureDefinition + .builder() + .addShape( + STRUCTURE_PIECE_MAIN, + transpose( + new String[][] { { "CCCCC", "CGGGC", "CGGGC", "CGGGC", "CCCCC" }, + { "CGGGC", "G---G", "G---G", "G---G", "CGGGC" }, + { "CGGGC", "G---G", "G-X-G", "G---G", "CGGGC" }, + { "CGGGC", "G---G", "G---G", "G---G", "CGGGC" }, + { "CC~CC", "CGGGC", "CGGGC", "CGGGC", "CCCCC" }, })) + .addElement( + 'C', + ofChain( + ofHatchAdder(MTELargeMolecularAssembler::addToLargeMolecularAssemblerList, CASING_INDEX, 1), + onElementPass(it -> it.casing++, ofBlock(GregTechAPI.sBlockCasings4, 0)))) + .addElement( + 'G', + ofBlockAnyMeta(AEApi.instance().definitions().blocks().quartzVibrantGlass().maybeBlock().get())) + .addElement('X', (IStructureElementCheckOnly) (mte, world, x, y, z) -> { + if (world.isAirBlock(x, y, z)) { + mte.craftingDisplayPoint = new CraftingDisplayPoint(world, x, y, z); + return true; + } + return false; + }).build(); + + private byte casing; + private CraftingDisplayPoint craftingDisplayPoint; + + private ItemStack cachedDataOrb; + private List> cachedAeJobs = new ArrayList<>(); + private boolean aeJobsDirty; + + private List cachedPatternDetails = new ArrayList<>(); + private Map> patternDetailCache = new IdentityHashMap<>(); + + private BaseActionSource requestSource; + private IItemList cachedOutputs = AEApi.instance().storage().createPrimitiveItemList(); + private boolean lastOutputFailed; + private long lastOutputTick; + private long tickCounter; + + public boolean hiddenCraftingFX; + + private AENetworkProxy gridProxy; + + public MTELargeMolecularAssembler(int aID, String aName, String aNameRegional) { + super(aID, aName, aNameRegional); + } + + public MTELargeMolecularAssembler(String aName) { + super(aName); + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { + return new MTELargeMolecularAssembler(this.mName); + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection side, ForgeDirection facing, + int colorIndex, boolean active, boolean redstoneLevel) { + if (side == facing) { + return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX), + TextureFactory.builder().addIcon(Textures.BlockIcons.OVERLAY_ME_HATCH).extFacing().build() }; + } + return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX) }; + } + + @Override + public boolean isCorrectMachinePart(ItemStack aStack) { + return true; + } + + @Override + public boolean checkRecipe(ItemStack aStack) { + return withAeJobs(($, aeJobs) -> { + mMaxProgresstime = 20; + long craftingProgressTime = 20; + long craftingEUt = EU_PER_TICK_CRAFTING; + mEUt = -EU_PER_TICK_BASIC; + // Tier EU_PER_TICK_CRAFTING == 2 + int extraTier = Math.max(0, GTUtility.getTier(getMaxInputVoltage()) - 2); + // The first two Overclocks reduce the Finish time to 0.5s and 0.25s + for (int i = 0; i < 2; i++) { + if (extraTier <= 0) break; + craftingProgressTime /= 2; + craftingEUt *= 4; + extraTier--; + } + // Subsequent Overclocks Double the number of Jobs finished at once + int parallel = 2 << extraTier; + craftingEUt = craftingEUt << 2 * extraTier; + List outputs = new ArrayList<>(); + for (List l : aeJobs.subList(0, Math.min(parallel, aeJobs.size()))) { + outputs.addAll(l); + } + if (!outputs.isEmpty()) { + aeJobs.subList(0, Math.min(parallel, aeJobs.size())).clear(); + aeJobsDirty = true; + lEUt = -craftingEUt; + mMaxProgresstime = (int) craftingProgressTime; + mOutputItems = outputs.toArray(new ItemStack[0]); + addCraftingFX(outputs.get(0)); + } + mEfficiency = 10000 - (getIdealStatus() - getRepairStatus()) * 1000; + mEfficiencyIncrease = 10000; + return true; + }); + } + + @Override + public void saveNBTData(NBTTagCompound aNBT) { + saveAeJobsIfNeeded(); + super.saveNBTData(aNBT); + + NBTTagList isList = new NBTTagList(); + for (IAEItemStack aeIS : cachedOutputs) { + if (aeIS.getStackSize() <= 0) break; + NBTTagCompound tag = new NBTTagCompound(); + NBTTagCompound isTag = new NBTTagCompound(); + aeIS.getItemStack().writeToNBT(isTag); + tag.setTag("itemStack", isTag); + tag.setLong("size", aeIS.getStackSize()); + isList.appendTag(tag); + } + aNBT.setTag(NBT_KEY_CACHED_OUTPUTS, isList); + + aNBT.setBoolean(NBT_KEY_CONFIG_HIDDEN_CRAFTING_FX, hiddenCraftingFX); + NBTTagCompound proxyTag = new NBTTagCompound(); + getProxy().writeToNBT(proxyTag); + aNBT.setTag("proxy", proxyTag); + } + + @Override + public void loadNBTData(NBTTagCompound aNBT) { + super.loadNBTData(aNBT); + + NBTBase nbtBase = aNBT.getTag(NBT_KEY_CACHED_OUTPUTS); + if (nbtBase instanceof NBTTagList isList) { + for (int i = 0; i < isList.tagCount(); i++) { + NBTTagCompound tag = isList.getCompoundTagAt(i); + NBTTagCompound isTag = tag.getCompoundTag("itemStack"); + long size = tag.getLong("size"); + ItemStack itemStack = GTUtility.loadItem(isTag); + IAEItemStack aeIS = AEApi.instance().storage().createItemStack(itemStack); + aeIS.setStackSize(size); + cachedOutputs.add(aeIS); + } + } + + hiddenCraftingFX = aNBT.getBoolean(NBT_KEY_CONFIG_HIDDEN_CRAFTING_FX); + if (aNBT.hasKey("proxy")) { + getProxy().readFromNBT(aNBT.getCompoundTag("proxy")); + } + } + + @Override + public int getMaxEfficiency(ItemStack aStack) { + return 10000; + } + + @Override + public int getDamageToComponent(ItemStack aStack) { + return 0; + } + + @Override + public boolean explodesOnComponentBreak(ItemStack aStack) { + return false; + } + + @Override + protected MultiblockTooltipBuilder createTooltip() { + return new MultiblockTooltipBuilder().addMachineType(MACHINE_TYPE) + .addInfo("Needs a Data Orb to be placed in the controller") + .addInfo( + "Basic: " + EnumChatFormatting.GREEN + + EU_PER_TICK_BASIC + + EnumChatFormatting.GRAY + + " EU/t, unaffected by overclocking") + .addInfo( + "Crafting: " + EnumChatFormatting.GREEN + + EU_PER_TICK_CRAFTING + + EnumChatFormatting.GRAY + + " EU/t, Finish " + + EnumChatFormatting.WHITE + + "2" + + EnumChatFormatting.GRAY + + " Jobs in " + + EnumChatFormatting.WHITE + + "1" + + EnumChatFormatting.GRAY + + "s") + .addInfo("The first two Overclocks:") + .addInfo( + "-Reduce the Finish time to " + EnumChatFormatting.WHITE + + "0.5" + + EnumChatFormatting.GRAY + + "s and " + + EnumChatFormatting.WHITE + + "0.25" + + EnumChatFormatting.GRAY + + "s") + .addInfo("Subsequent Overclocks:").addInfo("-Double the number of Jobs finished at once") + .addInfo("Use the screwdriver to right-click the Controller to open the config GUI") + .beginStructureBlock(5, 5, 5, true).addController("Front center") + .addCasingInfoMin("Robust Tungstensteel Machine Casing", MIN_CASING_COUNT, false) + .addInputBus("Any casing", 1).addEnergyHatch("Any casing", 1).addMaintenanceHatch("Any casing", 1) + .toolTipFinisher(); + } + + @Override + public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { + casing = 0; + if (!checkPiece( + STRUCTURE_PIECE_MAIN, + STRUCTURE_HORIZONTAL_OFFSET, + STRUCTURE_VERTICAL_OFFSET, + STRUCTURE_DEPTH_OFFSET)) { + return false; + } + + if (mMaintenanceHatches.size() != 1 || mEnergyHatches.isEmpty()) { + return false; + } + + return casing >= MIN_CASING_COUNT; + } + + @Override + public void construct(ItemStack stackSize, boolean hintsOnly) { + buildPiece( + STRUCTURE_PIECE_MAIN, + stackSize, + hintsOnly, + STRUCTURE_HORIZONTAL_OFFSET, + STRUCTURE_VERTICAL_OFFSET, + STRUCTURE_DEPTH_OFFSET); + } + + @Override + public IStructureDefinition getStructureDefinition() { + return STRUCTURE_DEFINITION; + } + + @Override + public boolean addOutput(ItemStack aStack) { + cachedOutputs.add(AEApi.instance().storage().createItemStack(aStack)); + markDirty(); + return true; + } + + @Override + public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + super.onPostTick(aBaseMetaTileEntity, aTick); + if (aBaseMetaTileEntity.isServerSide()) { + flushCachedOutputsIfNeeded(aTick); + saveAeJobsIfNeeded(); + syncAEProxyActive(aBaseMetaTileEntity); + issuePatternChangeIfNeeded(aTick); + } + } + + @Override + public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ, + ItemStack aTool) { + super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ, aTool); + if (getBaseMetaTileEntity().isClientSide() || !(aPlayer instanceof EntityPlayerMP playerMP)) return; + if (side == getBaseMetaTileEntity().getFrontFacing()) { + MXRandom.network.sendTo(new MessageSyncMetaTileEntityConfig(this, true), playerMP); + } + } + + // dataOrb, aeJobs + private boolean withAeJobs(BiFunction>, Boolean> action) { + if (mInventory[1] == cachedDataOrb && cachedDataOrb != null) { + return action.apply(cachedDataOrb, cachedAeJobs); + } + if (!ItemList.Tool_DataOrb.isStackEqual(mInventory[1], false, true)) { + cachedDataOrb = null; + cachedAeJobs = null; + return false; + } + ItemStack dataOrb = mInventory[1]; + String dataTitle = BehaviourDataOrb.getDataTitle(dataOrb); + if (dataTitle == null || dataTitle.isEmpty()) { + dataTitle = DATA_ORB_TITLE; + BehaviourDataOrb.setDataName(dataOrb, dataTitle); + BehaviourDataOrb.setNBTInventory(dataOrb, new ItemStack[0]); + } + if (!dataTitle.equals(DATA_ORB_TITLE)) { + cachedDataOrb = null; + cachedAeJobs = null; + return false; + } + cachedDataOrb = dataOrb; + NBTTagCompound tag = dataOrb.getTagCompound(); + if (tag != null && tag.hasKey("Inventory", Constants.NBT.TAG_LIST)) { + List> jobs = new ArrayList<>(); + ItemStack[] stacks = BehaviourDataOrb.getNBTInventory(dataOrb); + for (ItemStack stack : stacks) { + if (stack == null) continue; + List l = new ArrayList<>(); + l.add(stack); + jobs.add(l); + } + cachedAeJobs = jobs; + } else if (tag != null && tag.hasKey(DATA_ORB_JOBS_KEY, Constants.NBT.TAG_LIST)) { + List> jobs = new ArrayList<>(); + NBTTagList tagList = tag.getTagList(DATA_ORB_JOBS_KEY, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < tagList.tagCount(); i++) { + NBTTagCompound jobTag = tagList.getCompoundTagAt(i); + NBTTagList jobTagList = jobTag.getTagList(DATA_ORB_JOBS_JOB_KEY, Constants.NBT.TAG_COMPOUND); + List stacks = new ArrayList<>(); + for (int j = 0; j < jobTagList.tagCount(); j++) { + ItemStack stack = GTUtility.loadItem(jobTagList.getCompoundTagAt(j)); + stacks.add(stack); + } + jobs.add(stacks); + } + cachedAeJobs = jobs; + } else { + cachedAeJobs = new ArrayList<>(); + } + return action.apply(cachedDataOrb, cachedAeJobs); + } + + private void addCraftingFX(ItemStack itemStack) { + if (hiddenCraftingFX) return; + if (craftingDisplayPoint != null) { + MXRandom.network.sendToAllAround( + new MessageCraftingFX( + craftingDisplayPoint.x, + craftingDisplayPoint.y, + craftingDisplayPoint.z, + mMaxProgresstime, + AEApi.instance().storage().createItemStack(itemStack)), + new NetworkRegistry.TargetPoint( + craftingDisplayPoint.w.provider.dimensionId, + craftingDisplayPoint.x, + craftingDisplayPoint.y, + craftingDisplayPoint.z, + 64)); + } + } + + private BaseActionSource getRequest() { + if (requestSource == null) { + requestSource = new MachineSource((IActionHost) getBaseMetaTileEntity()); + } + return requestSource; + } + + private void flushCachedOutputsIfNeeded(long tick) { + tickCounter = tick; + if (tickCounter <= lastOutputTick + 40) { + return; + } + + lastOutputFailed = true; + try { + AENetworkProxy proxy = getProxy(); + if (proxy == null) return; + IMEMonitor storage = proxy.getStorage().getItemInventory(); + for (IAEItemStack s : cachedOutputs) { + if (s.getStackSize() == 0) { + continue; + } + IAEItemStack rest = Platform.poweredInsert(proxy.getEnergy(), storage, s, getRequest()); + if (rest != null && rest.getStackSize() > 0) { + lastOutputFailed = true; + s.setStackSize(rest.getStackSize()); + break; + } + s.setStackSize(0); + } + } catch (GridAccessException ignored) { + lastOutputFailed = true; + } + lastOutputTick = tickCounter; + } + + private void saveAeJobsIfNeeded() { + if (!aeJobsDirty) { + return; + } + withAeJobs((dataOrb, aeJobs) -> { + NBTTagList jobList = new NBTTagList(); + for (var job : aeJobs) { + NBTTagCompound jobTag = new NBTTagCompound(); + NBTTagList itemList = new NBTTagList(); + for (var item : job) { + itemList.appendTag(GTUtility.saveItem(item)); + } + jobTag.setTag(DATA_ORB_JOBS_JOB_KEY, itemList); + } + dataOrb.stackTagCompound.setTag(DATA_ORB_JOBS_KEY, jobList); + markDirty(); + aeJobsDirty = false; + return true; + }); + } + + private void issuePatternChangeIfNeeded(long tick) { + if (tick % 20 != 0) { + return; + } + + Set inputs = GTUtility.filterValidMTEs(mInputBusses).stream() + .filter(bus -> !(bus instanceof MTEHatchCraftingInputME)) + .flatMap(bus -> IntStream.range(0, bus.getSizeInventory()).mapToObj(bus::getStackInSlot)) + .filter(Objects::nonNull).collect(Collectors.toSet()); + + List patterns = inputs.stream().map(is -> { + if (!(is.getItem() instanceof ItemEncodedPattern pattern)) { + return null; + } + var entry = patternDetailCache.get(is); + if (entry == null || !Objects.equals(is.getTagCompound(), entry.getKey())) { + ICraftingPatternDetails detail = pattern.getPatternForItem(is, getBaseMetaTileEntity().getWorld()); + patternDetailCache.put(is, Pair.of(is.getTagCompound(), detail)); + return detail; + } + return entry.getValue(); + }).filter(Objects::nonNull).filter(it -> ((ICraftingPatternDetails) it).isCraftable()) + .collect(Collectors.toList()); + if (patterns.equals(cachedPatternDetails)) return; + cachedPatternDetails = patterns; + patternDetailCache.keySet().retainAll(inputs); + + try { + AENetworkProxy proxy = getProxy(); + if (proxy == null) return; + proxy.getGrid().postEvent(new MENetworkCraftingPatternChange(this, getProxy().getNode())); + } catch (GridAccessException ignored) {} + } + + private void syncAEProxyActive(IGregTechTileEntity baseMetaTileEntity) { + AENetworkProxy proxy = getProxy(); + if (proxy == null) return; + if (baseMetaTileEntity.isActive()) { + if (!proxy.isReady()) { + proxy.onReady(); + IGridNode node = proxy.getNode(); + if (node == null) return; + if (node.getPlayerID() == -1) { + MXRandom.logger.warn( + "Found a LMA at {} without valid AE playerID.", + ((BaseMetaTileEntity) baseMetaTileEntity).getLocation()); + MXRandom.logger.warn("Try to recover playerID with UUID: {}", baseMetaTileEntity.getOwnerUuid()); + // recover ID from old version + int playerAEID = WorldData.instance().playerData().getPlayerID( + new GameProfile(baseMetaTileEntity.getOwnerUuid(), baseMetaTileEntity.getOwnerName())); + node.setPlayerID(playerAEID); + ((GridNode) node).setLastSecurityKey(-1); + node.updateState(); // refresh the security connection + MXRandom.logger.warn("Now it has playerID: {}", playerAEID); + } + } + + if (proxy.getConnectableSides().isEmpty()) { + proxy.setValidSides(EnumSet.complementOf(EnumSet.of(ForgeDirection.UNKNOWN))); + } + } else { + if (!proxy.getConnectableSides().isEmpty()) { + proxy.setValidSides(EnumSet.noneOf(ForgeDirection.class)); + } + } + } + + private boolean addToLargeMolecularAssemblerList(IGregTechTileEntity tileEntity, short baseCasingIndex) { + if (addMaintenanceToMachineList(tileEntity, baseCasingIndex)) return true; + if (addInputToMachineList(tileEntity, baseCasingIndex)) return true; + return addEnergyInputToMachineList(tileEntity, baseCasingIndex); + } + + @Override + public void readConfigFromBytes(ByteBuf buf) { + hiddenCraftingFX = buf.readBoolean(); + } + + @Override + public void writeConfigToBytes(ByteBuf buf) { + buf.writeBoolean(hiddenCraftingFX); + } + + @Override + public Object getServerGuiElement(int ID, EntityPlayer player) { + return new ContainerConfigLargeMolecularAssembler(this); + } + + @SideOnly(Side.CLIENT) + @Override + public Object getClientGuiElement(int ID, EntityPlayer player) { + return new GuiConfigLargeMolecularAssembler(new ContainerConfigLargeMolecularAssembler(this)); + } + + @Override + public boolean pushPattern(ICraftingPatternDetails patternDetails, InventoryCrafting table) { + return withAeJobs(($, aeJobs) -> { + World w = getBaseMetaTileEntity().getWorld(); + ItemStack mainOutput = patternDetails.getOutput(table, w); + if (mainOutput == null) return false; + + FMLCommonHandler.instance().firePlayerCraftingEvent(Platform.getPlayer((WorldServer) w), mainOutput, table); + + List leftover = IntStream.range(0, table.getSizeInventory() + 1) + .mapToObj(i -> Platform.getContainerItem(table.getStackInSlot(i))).filter(Objects::nonNull) + .collect(Collectors.toList()); + leftover.add(mainOutput); + aeJobs.add(leftover); + aeJobsDirty = true; + return true; + }); + } + + @Override + public boolean isBusy() { + return withAeJobs(($, aeJobs) -> aeJobs.size() >= 256); + } + + @Override + public void provideCrafting(ICraftingProviderHelper craftingTracker) { + AENetworkProxy proxy = getProxy(); + if (proxy == null) return; + if (proxy.isReady()) { + for (ICraftingPatternDetails detail : cachedPatternDetails) { + craftingTracker.addCraftingOption(this, detail); + } + } + } + + @Override + public AENetworkProxy getProxy() { + if (gridProxy == null) { + gridProxy = new AENetworkProxy(this, "proxy", getStackForm(1), true); + gridProxy.setFlags(GridFlags.REQUIRE_CHANNEL); + if (getBaseMetaTileEntity().getWorld() != null) { + EntityPlayer player = getBaseMetaTileEntity().getWorld() + .getPlayerEntityByName(getBaseMetaTileEntity().getOwnerName()); + gridProxy.setOwner(player); + } + } + return gridProxy; + } + + @Override + public IGridNode getGridNode(ForgeDirection dir) { + AENetworkProxy proxy = getProxy(); + if (proxy == null) return null; + return proxy.getNode(); + } + + @Override + public void securityBreak() { + getBaseMetaTileEntity().disableWorking(); + } + + @Override + public DimensionalCoord getLocation() { + return new DimensionalCoord( + getBaseMetaTileEntity().getWorld(), + getBaseMetaTileEntity().getXCoord(), + getBaseMetaTileEntity().getYCoord(), + getBaseMetaTileEntity().getZCoord()); + } + + @Override + public IGridNode getActionableNode() { + return getProxy().getNode(); + } + + @SuppressWarnings("all") + private static class CraftingDisplayPoint { + + private final World w; + private final int x; + private final int y; + private final int z; + + private CraftingDisplayPoint(World w, int x, int y, int z) { + this.w = w; + this.x = x; + this.y = y; + this.z = z; + } + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/network/GuiHandler.java b/src/main/java/com/muxiu1997/mxrandom/network/GuiHandler.java new file mode 100644 index 0000000..21524b8 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/network/GuiHandler.java @@ -0,0 +1,37 @@ +package com.muxiu1997.mxrandom.network; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; + +import com.muxiu1997.mxrandom.Utils; +import com.muxiu1997.mxrandom.api.IConfigurableMetaTileEntity; + +import cpw.mods.fml.common.network.IGuiHandler; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; + +public class GuiHandler implements IGuiHandler { + + private static final int ID_CONFIG_META_TILE_ENTITY = 1; + + @Override + public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { + if (ID == ID_CONFIG_META_TILE_ENTITY) { + IMetaTileEntity mte = Utils.getMetaTileEntity(world, x, y, z); + if (mte instanceof IConfigurableMetaTileEntity icmte) { + return icmte.getServerGuiElement(ID, player); + } + } + return null; + } + + @Override + public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { + if (ID == ID_CONFIG_META_TILE_ENTITY) { + IMetaTileEntity mte = Utils.getMetaTileEntity(world, x, y, z); + if (mte instanceof IConfigurableMetaTileEntity icmte) { + return icmte.getClientGuiElement(ID, player); + } + } + return null; + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/network/container/ContainerConfigLargeMolecularAssembler.java b/src/main/java/com/muxiu1997/mxrandom/network/container/ContainerConfigLargeMolecularAssembler.java new file mode 100644 index 0000000..a15a42e --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/network/container/ContainerConfigLargeMolecularAssembler.java @@ -0,0 +1,20 @@ +package com.muxiu1997.mxrandom.network.container; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; + +import com.muxiu1997.mxrandom.metatileentity.MTELargeMolecularAssembler; + +public class ContainerConfigLargeMolecularAssembler extends Container { + + public final MTELargeMolecularAssembler LMA; + + public ContainerConfigLargeMolecularAssembler(MTELargeMolecularAssembler LMA) { + this.LMA = LMA; + } + + @Override + public boolean canInteractWith(EntityPlayer player) { + return true; + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/network/message/MessageCraftingFX.java b/src/main/java/com/muxiu1997/mxrandom/network/message/MessageCraftingFX.java new file mode 100644 index 0000000..ab64ae0 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/network/message/MessageCraftingFX.java @@ -0,0 +1,80 @@ +package com.muxiu1997.mxrandom.network.message; + +import java.io.IOException; + +import net.minecraft.client.Minecraft; + +import com.muxiu1997.mxrandom.MXRandom; +import com.muxiu1997.mxrandom.api.network.IMessageClientSideHandler; +import com.muxiu1997.mxrandom.client.fx.CraftingFX; + +import appeng.api.storage.data.IAEItemStack; +import appeng.util.item.AEItemStack; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; + +public class MessageCraftingFX implements IMessage { + + private int x; + private int y; + private int z; + private int age; + private IAEItemStack itemStack; + + @SuppressWarnings("unused") + public MessageCraftingFX() {} + + public MessageCraftingFX(int x, int y, int z, int age, IAEItemStack itemStack) { + this.x = x; + this.y = y; + this.z = z; + this.age = age; + this.itemStack = itemStack; + } + + @Override + public void fromBytes(ByteBuf buf) { + this.x = buf.readInt(); + this.y = buf.readInt(); + this.z = buf.readInt(); + this.age = buf.readInt(); + try { + this.itemStack = AEItemStack.loadItemStackFromPacket(buf); + } catch (IOException e) { + MXRandom.logger.error("Could not deserialize LMA ItemStack", e); + } + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeInt(x); + buf.writeInt(y); + buf.writeInt(z); + buf.writeInt(age); + try { + itemStack.writeToPacket(buf); + } catch (IOException e) { + MXRandom.logger.error("Could not serialize LMA ItemStack", e); + } + } + + public static class Handler implements IMessageClientSideHandler { + + @SideOnly(Side.CLIENT) + @Override + public IMessage handleClientSideMessage(MessageCraftingFX message, MessageContext ctx) { + CraftingFX fx = new CraftingFX( + Minecraft.getMinecraft().theWorld, + message.x, + message.y, + message.z, + message.age, + message.itemStack); + Minecraft.getMinecraft().effectRenderer.addEffect(fx); + return null; + } + } +} diff --git a/src/main/java/com/muxiu1997/mxrandom/network/message/MessageSyncMetaTileEntityConfig.java b/src/main/java/com/muxiu1997/mxrandom/network/message/MessageSyncMetaTileEntityConfig.java new file mode 100644 index 0000000..6c38511 --- /dev/null +++ b/src/main/java/com/muxiu1997/mxrandom/network/message/MessageSyncMetaTileEntityConfig.java @@ -0,0 +1,113 @@ +package com.muxiu1997.mxrandom.network.message; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +import com.muxiu1997.mxrandom.MXRandom; +import com.muxiu1997.mxrandom.Utils; +import com.muxiu1997.mxrandom.api.IConfigurableMetaTileEntity; +import com.muxiu1997.mxrandom.api.network.IMessageBothSideHandler; + +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +public class MessageSyncMetaTileEntityConfig implements IMessage { + + private int x; + private int y; + private int z; + private int dimID; + private ByteBuf configData; + private boolean openGui; + + @SuppressWarnings("unused") + public MessageSyncMetaTileEntityConfig() {} + + public MessageSyncMetaTileEntityConfig(IConfigurableMetaTileEntity mte, boolean openGui) { + IGregTechTileEntity igtte = mte.getBaseMetaTileEntity(); + this.x = igtte.getXCoord(); + this.y = igtte.getYCoord(); + this.z = igtte.getZCoord(); + this.dimID = igtte.getWorld().provider.dimensionId; + this.configData = Unpooled.buffer(); + mte.writeConfigToBytes(this.configData); + this.openGui = openGui; + } + + public MessageSyncMetaTileEntityConfig(int x, int y, int z, int dimID, ByteBuf configData, boolean openGui) { + this.x = x; + this.y = y; + this.z = z; + this.dimID = dimID; + this.configData = configData; + this.openGui = openGui; + } + + @Override + public void fromBytes(ByteBuf buf) { + this.x = buf.readInt(); + this.y = buf.readInt(); + this.z = buf.readInt(); + this.dimID = buf.readInt(); + this.configData = buf.readBytes(buf.readInt()); + this.openGui = buf.readBoolean(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeInt(this.x); + buf.writeInt(this.y); + buf.writeInt(this.z); + buf.writeInt(this.dimID); + buf.writeInt(this.configData.readableBytes()); + buf.writeBytes(this.configData); + buf.writeBoolean(this.openGui); + } + + public static class Handler implements IMessageBothSideHandler { + + @SideOnly(Side.CLIENT) + @Override + public IMessage handleClientSideMessage(MessageSyncMetaTileEntityConfig message, MessageContext ctx) { + World world = DimensionManager.getWorld(message.dimID); + if (world == null) { + return null; + } + + IMetaTileEntity mte = Utils.getMetaTileEntity(world, message.x, message.y, message.z); + if (mte instanceof IConfigurableMetaTileEntity icmte) { + icmte.readConfigFromBytes(message.configData); + if (message.openGui) { + Minecraft.getMinecraft().thePlayer + .openGui(MXRandom.MODID, 1, world, message.x, message.y, message.z); + } + } + return null; + } + + @Override + public IMessage handleServerSideMessage(MessageSyncMetaTileEntityConfig message, MessageContext ctx) { + World world = DimensionManager.getWorld(message.dimID); + if (world == null) { + return null; + } + + IMetaTileEntity mte = Utils.getMetaTileEntity(world, message.x, message.y, message.z); + if (mte instanceof IConfigurableMetaTileEntity icmte) { + ByteBuf configData = message.configData.copy(); + icmte.readConfigFromBytes(message.configData); + message.openGui = false; + message.configData = configData; + MXRandom.network.sendToAll(message); + } + return null; + } + } +} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/Extensions.kt b/src/main/kotlin/com/muxiu1997/mxrandom/Extensions.kt deleted file mode 100644 index d946458..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/Extensions.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.muxiu1997.mxrandom - -import gregtech.api.interfaces.metatileentity.IMetaTileEntity -import gregtech.api.interfaces.tileentity.IGregTechTileEntity -import net.minecraft.world.World - -// region net.minecraft.world.World -@JvmName("getMetaTileEntity") -fun World.getMetaTileEntity(x: Int, y: Int, z: Int): IMetaTileEntity? { - val baseMetaTileEntity = this.getTileEntity(x, y, z) as? IGregTechTileEntity ?: return null - return baseMetaTileEntity.metaTileEntity -} - -@JvmName("getMetaTileEntityByClass") -inline fun World.getMetaTileEntity(x: Int, y: Int, z: Int): T? { - return this.getMetaTileEntity(x, y, z) as? T -} -// endregion diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/MXRandom.kt b/src/main/kotlin/com/muxiu1997/mxrandom/MXRandom.kt deleted file mode 100644 index 25314e9..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/MXRandom.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.muxiu1997.mxrandom - -import com.muxiu1997.mxrandom.proxy.CommonProxy -import cpw.mods.fml.common.Mod -import cpw.mods.fml.common.SidedProxy -import cpw.mods.fml.common.event.FMLInitializationEvent -import cpw.mods.fml.common.event.FMLPostInitializationEvent -import cpw.mods.fml.common.network.NetworkRegistry -import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper -import org.apache.logging.log4j.LogManager -import org.apache.logging.log4j.Logger - -@Mod( - modid = MODID, - name = MODNAME, - version = VERSION, - modLanguageAdapter = "net.shadowfacts.forgelin.KotlinAdapter", - dependencies = - "" + - "required-after:forgelin;" + - "required-after:appliedenergistics2;" + - "required-after:gregtech", -) -object MXRandomMod { - @SidedProxy( - serverSide = "$GROUPNAME.proxy.CommonProxy", clientSide = "$GROUPNAME.proxy.ClientProxy") - lateinit var proxy: CommonProxy - - @Mod.EventHandler - fun onInit(@Suppress("UNUSED_PARAMETER") e: FMLInitializationEvent) { - proxy.onInit(e) - } - - @Mod.EventHandler - fun onPostInit(@Suppress("UNUSED_PARAMETER") e: FMLPostInitializationEvent) { - proxy.onPostInit(e) - } -} - -@Suppress("unused", "MemberVisibilityCanBePrivate", "FunctionName") -object MXRandom { - // region Logger - val logger: Logger = LogManager.getLogger(MODID) - fun debug(message: Any) { - logger.debug("[$MODNAME]$message") - } - - fun info(message: Any) { - logger.info("[$MODNAME]$message") - } - - fun warn(message: Any) { - logger.warn("[$MODNAME]$message") - } - - fun error(message: Any) { - logger.error("[$MODNAME]$message") - } - - fun Any._debug() = debug(this) - - fun Any._info() = info(this) - - fun Any._warn() = warn(this) - - fun Any._error() = error(this) - // endregion - - const val MTE_ID_OFFSET = 14100 - - val network: SimpleNetworkWrapper = NetworkRegistry.INSTANCE.newSimpleChannel(MODID) -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/api/IConfigurableMetaTileEntity.kt b/src/main/kotlin/com/muxiu1997/mxrandom/api/IConfigurableMetaTileEntity.kt deleted file mode 100644 index 06e0fb6..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/api/IConfigurableMetaTileEntity.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.muxiu1997.mxrandom.api - -import com.muxiu1997.mxrandom.MXRandom.network -import com.muxiu1997.mxrandom.network.message.MessageSyncMetaTileEntityConfig -import gregtech.api.interfaces.tileentity.IGregTechTileEntity -import io.netty.buffer.ByteBuf -import net.minecraft.entity.player.EntityPlayer -import net.minecraftforge.common.util.ForgeDirection - -interface IConfigurableMetaTileEntity { - fun getBaseMetaTileEntity(): IGregTechTileEntity - - fun readConfigFromBytes(buf: ByteBuf) - - fun writeConfigToBytes(buf: ByteBuf) - - fun applyConfigChanges() { - val baseMetaTileEntity = getBaseMetaTileEntity() - baseMetaTileEntity.markDirty() - when { - baseMetaTileEntity.isClientSide -> network.sendToServer(MessageSyncMetaTileEntityConfig(this)) - baseMetaTileEntity.isServerSide -> network.sendToAll(MessageSyncMetaTileEntityConfig(this)) - } - } - - fun getServerGuiElement(ID: Int, player: EntityPlayer?): Any? - - fun getClientGuiElement(ID: Int, player: EntityPlayer?): Any? - fun onScrewdriverRightClick( - side: ForgeDirection?, - player: EntityPlayer?, - x: Float, - y: Float, - z: Float - ) -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/api/network/IMessageBothSideHandler.kt b/src/main/kotlin/com/muxiu1997/mxrandom/api/network/IMessageBothSideHandler.kt deleted file mode 100644 index c937e8b..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/api/network/IMessageBothSideHandler.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.muxiu1997.mxrandom.api.network - -import cpw.mods.fml.common.network.simpleimpl.IMessage -import cpw.mods.fml.common.network.simpleimpl.MessageContext -import cpw.mods.fml.relauncher.Side - -interface IMessageBothSideHandler : - IMessageServerSideHandler, IMessageClientSideHandler { - override fun onMessage(message: REQ, ctx: MessageContext): REPLY { - return if (ctx.side == Side.SERVER) { - handleServerSideMessage(message, ctx) - } else { - handleClientSideMessage(message, ctx) - } - } -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/api/network/IMessageClientSideHandler.kt b/src/main/kotlin/com/muxiu1997/mxrandom/api/network/IMessageClientSideHandler.kt deleted file mode 100644 index cfc518b..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/api/network/IMessageClientSideHandler.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.muxiu1997.mxrandom.api.network - -import cpw.mods.fml.common.network.simpleimpl.IMessage -import cpw.mods.fml.common.network.simpleimpl.IMessageHandler -import cpw.mods.fml.common.network.simpleimpl.MessageContext - -interface IMessageClientSideHandler : - IMessageHandler { - override fun onMessage(message: REQ, ctx: MessageContext): REPLY { - if (ctx.side.isServer) { - throw IllegalAccessError("Cannot handle server-side messages") - } - return handleClientSideMessage(message, ctx) - } - - fun handleClientSideMessage(message: REQ, ctx: MessageContext): REPLY -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/api/network/IMessageServerSideHandler.kt b/src/main/kotlin/com/muxiu1997/mxrandom/api/network/IMessageServerSideHandler.kt deleted file mode 100644 index 5d4daf0..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/api/network/IMessageServerSideHandler.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.muxiu1997.mxrandom.api.network - -import cpw.mods.fml.common.network.simpleimpl.IMessage -import cpw.mods.fml.common.network.simpleimpl.IMessageHandler -import cpw.mods.fml.common.network.simpleimpl.MessageContext - -interface IMessageServerSideHandler : - IMessageHandler { - override fun onMessage(message: REQ, ctx: MessageContext): REPLY { - if (ctx.side.isClient) { - throw IllegalAccessError("Cannot handle client-side messages") - } - return handleServerSideMessage(message, ctx) - } - - fun handleServerSideMessage(message: REQ, ctx: MessageContext): REPLY -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/client/fx/CraftingFX.kt b/src/main/kotlin/com/muxiu1997/mxrandom/client/fx/CraftingFX.kt deleted file mode 100644 index 697e8d8..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/client/fx/CraftingFX.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.muxiu1997.mxrandom.client.fx - -import appeng.api.storage.data.IAEItemStack -import net.minecraft.client.Minecraft -import net.minecraft.client.particle.EntityFX -import net.minecraft.client.renderer.Tessellator -import net.minecraft.client.renderer.entity.RenderManager -import net.minecraft.entity.item.EntityItem -import net.minecraft.item.ItemBlock -import net.minecraft.util.MathHelper -import net.minecraft.world.World -import org.lwjgl.opengl.GL11 - -class CraftingFX(w: World, x: Double, y: Double, z: Double, age: Int, itemStack: IAEItemStack) : - EntityFX(w, x, y, z, 0.0, 0.0, 0.0) { - private val entityItem = - EntityItem(worldObj, 0.0, 0.0, 0.0, itemStack.itemStack).also { it.hoverStart = 0.0f } - private val isItemBlock = itemStack.itemStack.item is ItemBlock - - init { - motionX = 0.0 - motionY = 0.0 - motionZ = 0.0 - particleMaxAge = age + 1 - noClip = true - } - - override fun renderParticle( - tess: Tessellator, - renderPartialTicks: Float, - rX: Float, - rY: Float, - rZ: Float, - rYZ: Float, - rXY: Float - ) { - Tessellator.instance.draw() - GL11.glPushMatrix() - - val ticks: Float = Minecraft.getMinecraft().renderViewEntity.ticksExisted.toFloat() - val x = (prevPosX + (posX - prevPosX) * renderPartialTicks - interpPosX) - val y = (prevPosY + (posY - prevPosY) * renderPartialTicks - interpPosY) - val z = (prevPosZ + (posZ - prevPosZ) * renderPartialTicks - interpPosZ) - val h = MathHelper.sin(ticks % 32767.0f / 16.0f) * 0.05f - val scale = if (isItemBlock) 3.6f else 1.8f - - GL11.glTranslatef((x + 0.5).toFloat(), (y + 0.15f + h).toFloat(), (z + 0.5).toFloat()) - GL11.glRotatef(ticks % 360.0f, 0.0f, 1.0f, 0.0f) - GL11.glScalef(scale, scale, scale) - - RenderManager.instance.renderEntityWithPosYaw(entityItem, 0.0, 0.0, 0.0, 0.0f, 0.0f) - - GL11.glPopMatrix() - Tessellator.instance.startDrawingQuads() - } - - override fun getBrightnessForRender(partialTickTime: Float): Int = - 15.let { (it shl 20) or (it shl 4) } - - override fun getFXLayer(): Int = if (isItemBlock) 1 else 2 - - override fun shouldRenderInPass(pass: Int): Boolean = pass == 2 -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/client/gui/GuiConfigLargeMolecularAssembler.kt b/src/main/kotlin/com/muxiu1997/mxrandom/client/gui/GuiConfigLargeMolecularAssembler.kt deleted file mode 100644 index 810c1ca..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/client/gui/GuiConfigLargeMolecularAssembler.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.muxiu1997.mxrandom.client.gui - -import com.muxiu1997.mxrandom.MODID -import com.muxiu1997.mxrandom.metatileentity.MTELargeMolecularAssembler -import com.muxiu1997.mxrandom.network.container.ContainerConfigLargeMolecularAssembler -import java.awt.Color -import net.minecraft.client.gui.GuiButton -import net.minecraft.client.gui.inventory.GuiContainer -import net.minecraft.util.ResourceLocation -import net.minecraft.util.StatCollector - -class GuiConfigLargeMolecularAssembler(GuiContainer: ContainerConfigLargeMolecularAssembler) : - GuiContainer(GuiContainer) { - @Suppress("PrivatePropertyName") private val LMA: MTELargeMolecularAssembler = GuiContainer.LMA - private lateinit var buttonToggleCraftingFX: GuiButton - - init { - xSize = 176 - ySize = 107 - } - - override fun initGui() { - super.initGui() - buttonToggleCraftingFX = - GuiButton( - 0, - guiLeft + xSize - BUTTON_WIDTH - PADDING, - guiTop + PADDING + 16, - BUTTON_WIDTH, - BUTTON_HEIGHT, - buttonToggleCraftingFXDisplayString()) - buttonList.add(buttonToggleCraftingFX) - } - - override fun updateScreen() { - super.updateScreen() - buttonToggleCraftingFX.displayString = buttonToggleCraftingFXDisplayString() - } - - override fun drawGuiContainerBackgroundLayer(partialTicks: Float, mouseX: Int, mouseY: Int) { - this.mc.textureManager.bindTexture(BACKGROUND_TEXTURE) - drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize) - } - - override fun drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) { - fontRendererObj.drawString(LMA.localName, PADDING, PADDING, Color.BLACK.rgb) - fontRendererObj.drawString(LANG_CRAFTING_FX, PADDING, PADDING + 20, Color.BLACK.rgb) - } - - override fun actionPerformed(button: GuiButton?) { - button ?: return - when (button) { - buttonToggleCraftingFX -> { - LMA.hiddenCraftingFX = !LMA.hiddenCraftingFX - LMA.applyConfigChanges() - } - } - } - - private fun buttonToggleCraftingFXDisplayString(): String { - return if (LMA.hiddenCraftingFX) { - LANG_HIDDEN - } else { - LANG_VISIBLE - } - } - - companion object { - val BACKGROUND_TEXTURE = ResourceLocation(MODID, "textures/gui/configMetaTileEntity.png") - const val PADDING = 8 - const val BUTTON_WIDTH = 40 - const val BUTTON_HEIGHT = 18 - - val LANG_CRAFTING_FX: String - get() = - StatCollector.translateToLocal( - "$MODID.client.gui.GuiConfigLargeMolecularAssembler.craftingFX") - val LANG_HIDDEN: String - get() = - StatCollector.translateToLocal( - "$MODID.client.gui.GuiConfigLargeMolecularAssembler.hidden") - val LANG_VISIBLE: String - get() = - StatCollector.translateToLocal( - "$MODID.client.gui.GuiConfigLargeMolecularAssembler.visible") - } -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/loader/GTMetaTileEntityLoader.kt b/src/main/kotlin/com/muxiu1997/mxrandom/loader/GTMetaTileEntityLoader.kt deleted file mode 100644 index db15d68..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/loader/GTMetaTileEntityLoader.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.muxiu1997.mxrandom.loader - -import com.muxiu1997.mxrandom.MODID -import com.muxiu1997.mxrandom.MXRandom.MTE_ID_OFFSET -import com.muxiu1997.mxrandom.metatileentity.MTELargeMolecularAssembler -import cpw.mods.fml.common.event.FMLInitializationEvent -import gregtech.api.metatileentity.implementations.MTEMultiBlockBase - -object GTMetaTileEntityLoader { - lateinit var largeMolecularAssembler: MTELargeMolecularAssembler - - fun load(@Suppress("UNUSED_PARAMETER") e: FMLInitializationEvent) { - largeMolecularAssembler = register(1, "Large Molecular Assembler") - } - - private inline fun register( - id: Int, - name: String, - unlocalizedName: String? = null - ): T { - val constructor = - T::class.java.getConstructor(Int::class.java, String::class.java, String::class.java) - val metaTileEntityUnlocalizedName = - MODID + (unlocalizedName ?: name.replace(" ", "").lowercase()) - return constructor.newInstance(MTE_ID_OFFSET + id, metaTileEntityUnlocalizedName, name) - } -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/loader/NetworkLoader.kt b/src/main/kotlin/com/muxiu1997/mxrandom/loader/NetworkLoader.kt deleted file mode 100644 index df18975..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/loader/NetworkLoader.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.muxiu1997.mxrandom.loader - -import com.muxiu1997.mxrandom.MODID -import com.muxiu1997.mxrandom.MXRandom -import com.muxiu1997.mxrandom.api.network.IMessageClientSideHandler -import com.muxiu1997.mxrandom.api.network.IMessageServerSideHandler -import com.muxiu1997.mxrandom.network.GuiHandler -import com.muxiu1997.mxrandom.network.message.MessageCraftingFX -import com.muxiu1997.mxrandom.network.message.MessageSyncMetaTileEntityConfig -import cpw.mods.fml.common.event.FMLInitializationEvent -import cpw.mods.fml.common.network.NetworkRegistry -import cpw.mods.fml.common.network.simpleimpl.IMessage -import cpw.mods.fml.common.network.simpleimpl.IMessageHandler -import cpw.mods.fml.relauncher.Side - -object NetworkLoader { - fun load(@Suppress("UNUSED_PARAMETER") e: FMLInitializationEvent) { - register(MessageCraftingFX.Companion.Handler) - register(MessageSyncMetaTileEntityConfig.Companion.Handler) - - NetworkRegistry.INSTANCE.registerGuiHandler(MODID, GuiHandler) - } - - private var networkMessageID = 0 - - private inline fun register(handler: IMessageHandler) { - if (handler is IMessageServerSideHandler) { - MXRandom.network.registerMessage(handler, M::class.java, networkMessageID++, Side.SERVER) - } - if (handler is IMessageClientSideHandler) { - MXRandom.network.registerMessage(handler, M::class.java, networkMessageID++, Side.CLIENT) - } - } -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/loader/RecipeLoader.kt b/src/main/kotlin/com/muxiu1997/mxrandom/loader/RecipeLoader.kt deleted file mode 100644 index 55a2079..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/loader/RecipeLoader.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.muxiu1997.mxrandom.loader - -import cpw.mods.fml.common.event.FMLPostInitializationEvent - -object RecipeLoader { - fun load(@Suppress("UNUSED_PARAMETER") e: FMLPostInitializationEvent) {} -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/metatileentity/MTELargeMolecularAssembler.kt b/src/main/kotlin/com/muxiu1997/mxrandom/metatileentity/MTELargeMolecularAssembler.kt deleted file mode 100644 index d32853c..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/metatileentity/MTELargeMolecularAssembler.kt +++ /dev/null @@ -1,677 +0,0 @@ -@file:Suppress("ClassName") - -package com.muxiu1997.mxrandom.metatileentity - -import appeng.api.AEApi -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.MENetworkCraftingPatternChange -import appeng.api.networking.security.BaseActionSource -import appeng.api.networking.security.IActionHost -import appeng.api.networking.security.MachineSource -import appeng.api.storage.data.IAEItemStack -import appeng.api.storage.data.IItemList -import appeng.api.util.DimensionalCoord -import appeng.core.worlddata.WorldData -import appeng.items.misc.ItemEncodedPattern -import appeng.me.GridAccessException -import appeng.me.GridNode -import appeng.me.helpers.AENetworkProxy -import appeng.me.helpers.IGridProxyable -import appeng.util.Platform -import com.gtnewhorizon.structurelib.structure.IStructureDefinition -import com.gtnewhorizon.structurelib.structure.IStructureElementCheckOnly -import com.gtnewhorizon.structurelib.structure.StructureDefinition -import com.gtnewhorizon.structurelib.structure.StructureUtility.* -import com.muxiu1997.mxrandom.MXRandom -import com.muxiu1997.mxrandom.MXRandom.network -import com.muxiu1997.mxrandom.api.IConfigurableMetaTileEntity -import com.muxiu1997.mxrandom.client.gui.GuiConfigLargeMolecularAssembler -import com.muxiu1997.mxrandom.network.container.ContainerConfigLargeMolecularAssembler -import com.muxiu1997.mxrandom.network.message.MessageCraftingFX -import com.muxiu1997.mxrandom.network.message.MessageSyncMetaTileEntityConfig -import cpw.mods.fml.common.FMLCommonHandler -import cpw.mods.fml.common.network.NetworkRegistry -import gregtech.api.GregTechAPI -import gregtech.api.enums.ItemList -import gregtech.api.enums.Textures.BlockIcons -import gregtech.api.interfaces.ITexture -import gregtech.api.interfaces.metatileentity.IMetaTileEntity -import gregtech.api.interfaces.tileentity.IGregTechTileEntity -import gregtech.api.metatileentity.BaseMetaTileEntity -import gregtech.api.metatileentity.implementations.MTEExtendedPowerMultiBlockBase -import gregtech.api.render.TextureFactory -import gregtech.api.util.GTStructureUtility.ofHatchAdder -import gregtech.api.util.GTUtility -import gregtech.api.util.MultiblockTooltipBuilder -import gregtech.common.items.behaviors.BehaviourDataOrb -import gregtech.common.tileentities.machines.MTEHatchCraftingInputME -import io.netty.buffer.ByteBuf -import java.util.* -import kotlin.collections.ArrayList -import kotlin.math.max -import kotlin.math.min -import net.minecraft.entity.player.EntityPlayer -import net.minecraft.entity.player.EntityPlayerMP -import net.minecraft.inventory.InventoryCrafting -import net.minecraft.item.ItemStack -import net.minecraft.nbt.NBTBase -import net.minecraft.nbt.NBTTagCompound -import net.minecraft.nbt.NBTTagList -import net.minecraft.util.EnumChatFormatting -import net.minecraft.world.World -import net.minecraft.world.WorldServer -import net.minecraftforge.common.util.Constants -import net.minecraftforge.common.util.ForgeDirection - -class MTELargeMolecularAssembler : - MTEExtendedPowerMultiBlockBase, - IConfigurableMetaTileEntity, - ICraftingProvider, - IActionHost, - IGridProxyable { - - private var casing: Byte = 0 - private var craftingDisplayPoint: CraftingDisplayPoint? = null - - private var cachedDataOrb: ItemStack? = null - private var cachedAeJobs: MutableList>? = ArrayList() - private var aeJobsDirty = false - - private var cachedPatternDetails: List = emptyList() - private val patternDetailCache: - MutableMap> = - IdentityHashMap() - - private var requestSource: BaseActionSource? = null - private var cachedOutputs = AEApi.instance().storage().createPrimitiveItemList() - private var lastOutputFailed = false - private var lastOutputTick: Long = 0 - private var tickCounter: Long = 0 - - var hiddenCraftingFX = false - - @Suppress("unused") - constructor(aID: Int, aName: String, aNameRegional: String) : super(aID, aName, aNameRegional) - - constructor(aName: String) : super(aName) - - // region GT_MetaTileEntity_EnhancedMultiBlockBase - override fun newMetaEntity(iGregTechTileEntity: IGregTechTileEntity): IMetaTileEntity { - return MTELargeMolecularAssembler(this.mName) - } - - override fun getTexture( - baseMetaTileEntity: IGregTechTileEntity?, - side: ForgeDirection?, - facing: ForgeDirection?, - colorIndex: Int, - active: Boolean, - redstone: Boolean - ): Array { - return when (side) { - facing -> - arrayOf( - BlockIcons.getCasingTextureForId(CASING_INDEX), - TextureFactory.builder().addIcon(BlockIcons.OVERLAY_ME_HATCH).extFacing().build(), - ) - else -> - arrayOf( - BlockIcons.getCasingTextureForId(CASING_INDEX), - ) - } - } - - override fun isCorrectMachinePart(aStack: ItemStack?): Boolean = true - - override fun checkRecipe(stack: ItemStack?): Boolean { - withAeJobs { _, aeJobs -> - mMaxProgresstime = 20 - var craftingProgressTime = 20 - var craftingEUt = EU_PER_TICK_CRAFTING.toLong() - mEUt = -EU_PER_TICK_BASIC - // Tier EU_PER_TICK_CRAFTING == 2 - var extraTier = max(0, GTUtility.getTier(maxInputVoltage).toInt() - 2) - // The first two Overclocks reduce the Finish time to 0.5s and 0.25s - for (i in 0 until 2) { - if (extraTier <= 0) break - craftingProgressTime /= 2 - craftingEUt *= 4 - extraTier-- - } - // Subsequent Overclocks Double the number of Jobs finished at once - val parallel = 2 shl extraTier - craftingEUt = craftingEUt shl 2 * extraTier - val outputs = aeJobs.take(parallel).flatten() - if (outputs.isNotEmpty()) { - aeJobs.subList(0, min(parallel, aeJobs.size)).clear() - aeJobsDirty = true - lEUt = -craftingEUt - mMaxProgresstime = craftingProgressTime - mOutputItems = outputs.toTypedArray() - addCraftingFX(outputs[0]) - } - mEfficiency = 10000 - (idealStatus - repairStatus) * 1000 - mEfficiencyIncrease = 10000 - return true - } - return false - } - - override fun saveNBTData(nbt: NBTTagCompound) { - saveAeJobsIfNeeded() - super.saveNBTData(nbt) - cachedOutputs.saveNBTData(nbt, NBT_KEY_CACHED_OUTPUTS) - nbt.setBoolean(NBT_KEY_CONFIG_HIDDEN_CRAFTING_FX, hiddenCraftingFX) - var proxyTag = NBTTagCompound() - proxy?.writeToNBT(proxyTag) - nbt.setTag("proxy", proxyTag) - } - - override fun loadNBTData(nbt: NBTTagCompound) { - super.loadNBTData(nbt) - cachedOutputs.loadNBTData(nbt, NBT_KEY_CACHED_OUTPUTS) - hiddenCraftingFX = nbt.getBoolean(NBT_KEY_CONFIG_HIDDEN_CRAFTING_FX) - if (nbt.hasKey("proxy")) proxy?.readFromNBT(nbt.getCompoundTag("proxy")) - } - - override fun getMaxEfficiency(aStack: ItemStack?): Int = 10000 - - override fun getDamageToComponent(aStack: ItemStack?): Int = 0 - - override fun explodesOnComponentBreak(aStack: ItemStack?): Boolean = false - - @Suppress("FunctionName") - override fun createTooltip(): MultiblockTooltipBuilder { - fun GREEN(thing: Any) = "${EnumChatFormatting.GREEN}$thing${EnumChatFormatting.GRAY}" - fun WHITE(thing: Any) = "${EnumChatFormatting.WHITE}$thing${EnumChatFormatting.GRAY}" - return MultiblockTooltipBuilder().also { - it.addMachineType(MACHINE_TYPE) - .addInfo("Needs a Data Orb to be placed in the controller") - .addInfo("Basic: ${GREEN(EU_PER_TICK_BASIC)} Eu/t, Unaffected by overclocking") - .addInfo( - "Crafting: ${GREEN(EU_PER_TICK_CRAFTING)} Eu/t, Finish ${WHITE(2)} Jobs in ${WHITE(1)}s") - .addInfo("The first two Overclocks:") - .addInfo("-Reduce the Finish time to ${WHITE(0.5)}s and ${WHITE(0.25)}s") - .addInfo("Subsequent Overclocks:") - .addInfo("-Double the number of Jobs finished at once") - .addInfo("Use the screwdriver to right-click the Controller to open the config GUI") - .beginStructureBlock(5, 5, 5, true) - .addController("Front center") - .addCasingInfoMin("Robust Tungstensteel Machine Casing", MIN_CASING_COUNT, false) - .addInputBus("Any casing", 1) - .addEnergyHatch("Any casing", 1) - .addMaintenanceHatch("Any casing", 1) - .toolTipFinisher() - } - } - - override fun checkMachine(baseMetaTileEntity: IGregTechTileEntity?, stack: ItemStack?): Boolean { - casing = 0 - return when { - !checkPiece( - STRUCTURE_PIECE_MAIN, - STRUCTURE_HORIZONTAL_OFFSET, - STRUCTURE_VERTICAL_OFFSET, - STRUCTURE_DEPTH_OFFSET) -> false - !checkHatches() -> false - casing < MIN_CASING_COUNT -> false - else -> true - } - } - - private fun checkHatches(): Boolean { - return when { - mMaintenanceHatches.size != 1 -> false - mEnergyHatches.isEmpty() -> false - else -> true - } - } - - override fun construct(itemStack: ItemStack?, hintsOnly: Boolean) { - buildPiece( - STRUCTURE_PIECE_MAIN, - itemStack, - hintsOnly, - STRUCTURE_HORIZONTAL_OFFSET, - STRUCTURE_VERTICAL_OFFSET, - STRUCTURE_DEPTH_OFFSET) - } - - override fun getStructureDefinition(): IStructureDefinition = - STRUCTURE_DEFINITION - - override fun addOutput(stack: ItemStack): Boolean { - cachedOutputs.add(AEApi.instance().storage().createItemStack(stack)) - markDirty() - return true - } - - override fun onPostTick(baseMetaTileEntity: IGregTechTileEntity, tick: Long) { - super.onPostTick(baseMetaTileEntity, tick) - if (baseMetaTileEntity.isServerSide) { - flushCachedOutputsIfNeeded(tick) - saveAeJobsIfNeeded() - syncAEProxyActive(baseMetaTileEntity) - issuePatternChangeIfNeeded(tick) - } - } - - override fun onScrewdriverRightClick( - side: ForgeDirection?, - player: EntityPlayer?, - x: Float, - y: Float, - z: Float - ) { - super.onScrewdriverRightClick(side, player, x, y, z) - if (baseMetaTileEntity.isClientSide || player !is EntityPlayerMP) return - if (side == baseMetaTileEntity.frontFacing) { - network.sendTo(MessageSyncMetaTileEntityConfig(this, true), player) - } - } - // endregion - - private inline fun withAeJobs( - action: (dataOrb: ItemStack, aeJobs: MutableList>) -> Unit - ) { - if (mInventory[1] === cachedDataOrb && cachedDataOrb != null) { - action(cachedDataOrb!!, cachedAeJobs!!) - return - } - if (!ItemList.Tool_DataOrb.isStackEqual(mInventory[1], false, true)) { - cachedDataOrb = null - cachedAeJobs = null - return - } - val dataOrb: ItemStack = mInventory[1] - var dataTitle: String = BehaviourDataOrb.getDataTitle(dataOrb) - if (dataTitle.isEmpty()) { - dataTitle = DATA_ORB_TITLE - BehaviourDataOrb.setDataTitle(dataOrb, dataTitle) - BehaviourDataOrb.setNBTInventory(dataOrb, emptyArray()) - } - if (dataTitle != DATA_ORB_TITLE) { - cachedDataOrb = null - cachedAeJobs = null - return - } - cachedDataOrb = dataOrb - if (dataOrb.stackTagCompound?.hasKey("Inventory", Constants.NBT.TAG_LIST) == true) { - cachedAeJobs = - BehaviourDataOrb.getNBTInventory(dataOrb).asSequence().filterNotNull().mapTo( - mutableListOf()) { listOf(it) } - } else if (dataOrb.stackTagCompound?.hasKey(DATA_ORB_JOBS_KEY, Constants.NBT.TAG_LIST) == - true) { - cachedAeJobs = - dataOrb.stackTagCompound - .getTagList(DATA_ORB_JOBS_KEY, Constants.NBT.TAG_COMPOUND) - .asCompoundSequence() - .map { - it.getTagList(DATA_ORB_JOBS_JOB_KEY, Constants.NBT.TAG_COMPOUND) - .asCompoundSequence() - .map { GTUtility.loadItem(it) } - .toList() - } - .toMutableList() - } else { - cachedAeJobs = mutableListOf() - } - action(cachedDataOrb!!, cachedAeJobs!!) - } - - private fun addCraftingFX(itemStack: ItemStack) { - if (hiddenCraftingFX) return - craftingDisplayPoint?.let { p -> - network.sendToAllAround( - MessageCraftingFX( - p.x, - p.y, - p.z, - mMaxProgresstime, - AEApi.instance().storage().createItemStack(itemStack)), - NetworkRegistry.TargetPoint( - p.w.provider.dimensionId, p.x.toDouble(), p.y.toDouble(), p.z.toDouble(), 64.0)) - } - } - - private fun getRequest(): BaseActionSource? { - if (requestSource == null) requestSource = MachineSource(baseMetaTileEntity as IActionHost) - return requestSource - } - - private fun flushCachedOutputsIfNeeded(tick: Long) { - tickCounter = tick - if (tickCounter <= lastOutputTick + 40) return - - lastOutputFailed = true - proxy?.let { - try { - val storage = it.storage.itemInventory - for (s in cachedOutputs) { - if (s.stackSize == 0L) continue - val rest = Platform.poweredInsert(it.energy, storage, s, getRequest()) - if (rest != null && rest.stackSize > 0) { - lastOutputFailed = true - s.stackSize = rest.stackSize - break - } - s.stackSize = 0 - } - } catch (ignored: GridAccessException) { - lastOutputFailed = true - } - } - lastOutputTick = tickCounter - } - - private fun saveAeJobsIfNeeded() { - if (!aeJobsDirty) return - withAeJobs { dataOrb, aeJobs -> - dataOrb.stackTagCompound.setTag( - DATA_ORB_JOBS_KEY, - aeJobs.mapToTagList { job -> - NBTTagCompound().also { - it.setTag(DATA_ORB_JOBS_JOB_KEY, job.mapToTagList { GTUtility.saveItem(it) }) - } - }) - markDirty() - aeJobsDirty = false - } - } - - private fun issuePatternChangeIfNeeded(tick: Long) { - if (tick % 20 != 0L) return - val inputs = - GTUtility.filterValidMTEs(mInputBusses) - .asSequence() - .filter { it !is MTEHatchCraftingInputME } - .flatMap { (0 until it.sizeInventory).asSequence().map { i -> it.getStackInSlot(i) } } - .filterNotNull() - .toSet() - val patterns = - inputs - .map { it.getPattern(baseMetaTileEntity.world) } - .filterNotNull() - .filter { it.isCraftable } - .toList() - if (patterns == cachedPatternDetails) return - cachedPatternDetails = patterns - patternDetailCache.keys.retainAll(inputs) - proxy?.let { - try { - it.grid.postEvent(MENetworkCraftingPatternChange(this, it.node)) - } catch (ignored: GridAccessException) { - // Do nothing - } - } - } - - private fun syncAEProxyActive(baseMetaTileEntity: IGregTechTileEntity) { - - proxy?.run { - if (baseMetaTileEntity.isActive) { - if (!isReady) { - onReady() - if (getProxy()?.getNode()?.getPlayerID() == -1) { - - MXRandom.logger.warn( - "Found a LMA at [${(baseMetaTileEntity as BaseMetaTileEntity).getLocation().toString()}] without valid AE playerID.") - MXRandom.logger.warn( - "Try to recover playerID with UUID:${baseMetaTileEntity.getOwnerUuid()}") - // recover ID from old version - var playerAEID = - WorldData.instance() - .playerData() - .getPlayerID( - com.mojang.authlib.GameProfile( - baseMetaTileEntity.getOwnerUuid(), baseMetaTileEntity.getOwnerName())) - - getProxy()?.getNode()?.setPlayerID(playerAEID) - var node = getProxy()?.getNode() as GridNode? - node?.setLastSecurityKey(-1L) - getProxy()?.getNode()?.updateState() // refresh the security connection - MXRandom.logger.warn("Now it has playerID:[$playerAEID]") - } - } - - if (getProxy()?.getConnectableSides()!!.isEmpty()) - getProxy()?.setValidSides(EnumSet.complementOf(EnumSet.of(ForgeDirection.UNKNOWN))) - } else { - if (!getProxy()?.getConnectableSides()!!.isEmpty()) - getProxy()?.setValidSides(EnumSet.noneOf(ForgeDirection::class.java)) - } - } - } - - private fun addToLargeMolecularAssemblerList( - tileEntity: IGregTechTileEntity?, - baseCasingIndex: Short - ): Boolean { - val casingIndex = baseCasingIndex.toInt() - return when { - addMaintenanceToMachineList(tileEntity, casingIndex) -> true - addInputToMachineList(tileEntity, casingIndex) -> true - addEnergyInputToMachineList(tileEntity, casingIndex) -> true - else -> false - } - } - - // region IConfigurableMetaTileEntity - override fun readConfigFromBytes(buf: ByteBuf) { - hiddenCraftingFX = buf.readBoolean() - } - - override fun writeConfigToBytes(buf: ByteBuf) { - buf.writeBoolean(hiddenCraftingFX) - } - - override fun getServerGuiElement(ID: Int, player: EntityPlayer?): Any { - return ContainerConfigLargeMolecularAssembler(this) - } - - override fun getClientGuiElement(ID: Int, player: EntityPlayer?): Any { - return GuiConfigLargeMolecularAssembler(ContainerConfigLargeMolecularAssembler(this)) - } - // endregion - - // region ICraftingProvider - override fun pushPattern( - patternDetails: ICraftingPatternDetails, - table: InventoryCrafting - ): Boolean { - withAeJobs { _, aeJobs -> - aeJobs.add( - patternDetails.getOutputs(table, baseMetaTileEntity.world)?.toList() ?: return false) - aeJobsDirty = true - return true - } - return false - } - - override fun isBusy(): Boolean { - withAeJobs { _, aeJobs -> if (aeJobs.size < 256) return false } - return true - } - - override fun provideCrafting(craftingTracker: ICraftingProviderHelper) { - if (proxy?.isReady == true) { - cachedPatternDetails.forEach { craftingTracker.addCraftingOption(this, it) } - } - } - // endregion - - // region IActionHost, IGridProxyable - private var gridProxy: AENetworkProxy? = null - - override fun getProxy(): AENetworkProxy? { - if (gridProxy == null) { - gridProxy = AENetworkProxy(this, "proxy", this.getStackForm(1), true) - gridProxy?.setFlags(GridFlags.REQUIRE_CHANNEL) - if (getBaseMetaTileEntity().getWorld() != null) { - val owner = - getBaseMetaTileEntity() - .getWorld() - .getPlayerEntityByName(getBaseMetaTileEntity().getOwnerName()) - gridProxy?.setOwner(owner) - } - } - - return gridProxy - } - - override fun getGridNode(dir: ForgeDirection?): IGridNode? { - return this.proxy?.node - } - - override fun securityBreak() { - baseMetaTileEntity.disableWorking() - } - - override fun getLocation(): DimensionalCoord { - return DimensionalCoord( - baseMetaTileEntity.world, - baseMetaTileEntity.xCoord, - baseMetaTileEntity.yCoord.toInt(), - baseMetaTileEntity.zCoord) - } - - override fun getActionableNode(): IGridNode? { - return this.proxy?.node - } - // endregion - - companion object { - private const val DATA_ORB_JOBS_KEY = "MX-CraftingJobs" - private const val DATA_ORB_JOBS_JOB_KEY = "Job" - private const val MACHINE_TYPE = "Molecular Assembler" - private const val EU_PER_TICK_BASIC = 16 - private const val EU_PER_TICK_CRAFTING = 64 - private const val CASING_INDEX = 48 - private const val MIN_CASING_COUNT = 24 - private const val DATA_ORB_TITLE = "AE-JOBS" - private const val NBT_KEY_CACHED_OUTPUTS = "cachedOutputs" - private const val NBT_KEY_CONFIG_HIDDEN_CRAFTING_FX = "config:hiddenCraftingFX" - private const val STRUCTURE_HORIZONTAL_OFFSET = 2 - private const val STRUCTURE_VERTICAL_OFFSET = 4 - private const val STRUCTURE_DEPTH_OFFSET = 0 - private const val STRUCTURE_PIECE_MAIN = "main" - - // region STRUCTURE_DEFINITION - private val STRUCTURE_DEFINITION = - StructureDefinition.builder() - .addShape( - STRUCTURE_PIECE_MAIN, - transpose( - arrayOf( - arrayOf("CCCCC", "CGGGC", "CGGGC", "CGGGC", "CCCCC"), - arrayOf("CGGGC", "G---G", "G---G", "G---G", "CGGGC"), - arrayOf("CGGGC", "G---G", "G-X-G", "G---G", "CGGGC"), - arrayOf("CGGGC", "G---G", "G---G", "G---G", "CGGGC"), - arrayOf("CC~CC", "CGGGC", "CGGGC", "CGGGC", "CCCCC"), - ))) - .addElement( - 'C', - ofChain( - ofHatchAdder( - MTELargeMolecularAssembler::addToLargeMolecularAssemblerList, - CASING_INDEX, - 1), - onElementPass({ it.casing++ }, ofBlock(GregTechAPI.sBlockCasings4, 0)), - )) - .addElement( - 'G', - ofBlockAnyMeta( - AEApi.instance() - .definitions() - .blocks() - .quartzVibrantGlass() - .maybeBlock() - .get())) - .addElement( - 'X', - IStructureElementCheckOnly { it, w, x, y, z -> - when { - w.isAirBlock(x, y, z) -> { - it.craftingDisplayPoint = CraftingDisplayPoint(w, x, y, z) - true - } - else -> false - } - }) - .build() - // endregion - - private data class CraftingDisplayPoint(val w: World, val x: Int, val y: Int, val z: Int) - - // region IItemList NBT - private fun IItemList.saveNBTData(nbt: NBTTagCompound, key: String) { - val isList = NBTTagList() - this.forEach { aeIS -> - if (aeIS.stackSize <= 0) return@forEach - val tag = NBTTagCompound() - val isTag = NBTTagCompound() - aeIS.itemStack.writeToNBT(isTag) - tag.setTag("itemStack", isTag) - tag.setLong("size", aeIS.stackSize) - isList.appendTag(tag) - } - nbt.setTag(key, isList) - } - - private fun IItemList.loadNBTData(nbt: NBTTagCompound, key: String) { - val isList = nbt.getTag(key) - if (isList !is NBTTagList) return - repeat(isList.tagCount()) { - val tag = isList.getCompoundTagAt(it) - val isTag = tag.getCompoundTag("itemStack") - val size = tag.getLong("size") - val itemStack = GTUtility.loadItem(isTag) - val aeIS = AEApi.instance().storage().createItemStack(itemStack) - aeIS.stackSize = size - this.add(aeIS) - } - } - // endregion - - private fun ICraftingPatternDetails.getOutputs( - ic: InventoryCrafting, - w: World - ): Sequence? { - val mainOutput = getOutput(ic, w) ?: return null - FMLCommonHandler.instance() - .firePlayerCraftingEvent(Platform.getPlayer(w as WorldServer), mainOutput, ic) - val leftover = - (0..ic.sizeInventory) - .asSequence() - .map { Platform.getContainerItem(ic.getStackInSlot(it)) } - .filterNotNull() + mainOutput - return leftover - } - - private fun NBTTagList.asCompoundSequence(): Sequence { - return (0..tagCount()).asSequence().map { getCompoundTagAt(it) } - } - - private inline fun Iterable.mapToTagList(action: (T) -> NBTBase): NBTTagList = - NBTTagList().also { for (e in this) it.appendTag(action(e)) } - } - - private fun ItemStack.getPattern(w: World): ICraftingPatternDetails? { - val item = this.item - if (item !is ItemEncodedPattern) return null - val (tag, detail) = patternDetailCache[this] ?: return getPatternRaw(w) - if (tag !== this.stackTagCompound) return getPatternRaw(w) - return detail - } - - private fun ItemStack.getPatternRaw(w: World): ICraftingPatternDetails { - val item = this.item as ItemEncodedPattern - val detail = item.getPatternForItem(this, w) - patternDetailCache[this] = Pair(stackTagCompound, detail) - return detail - } -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/network/GuiHandler.kt b/src/main/kotlin/com/muxiu1997/mxrandom/network/GuiHandler.kt deleted file mode 100644 index df5ac77..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/network/GuiHandler.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.muxiu1997.mxrandom.network - -import com.muxiu1997.mxrandom.api.IConfigurableMetaTileEntity -import com.muxiu1997.mxrandom.getMetaTileEntity -import cpw.mods.fml.common.network.IGuiHandler -import net.minecraft.entity.player.EntityPlayer -import net.minecraft.world.World - -object GuiHandler : IGuiHandler { - const val ID_CONFIG_META_TILE_ENTITY = 1 - - override fun getServerGuiElement( - ID: Int, - player: EntityPlayer?, - world: World?, - x: Int, - y: Int, - z: Int - ): Any? { - when (ID) { - ID_CONFIG_META_TILE_ENTITY -> { - val metaTileEntity = - world?.getMetaTileEntity(x, y, z) as? IConfigurableMetaTileEntity ?: return null - return metaTileEntity.getServerGuiElement(ID, player) - } - } - return null - } - - override fun getClientGuiElement( - ID: Int, - player: EntityPlayer?, - world: World?, - x: Int, - y: Int, - z: Int - ): Any? { - when (ID) { - ID_CONFIG_META_TILE_ENTITY -> { - val metaTileEntity = - world?.getMetaTileEntity(x, y, z) as? IConfigurableMetaTileEntity ?: return null - return metaTileEntity.getClientGuiElement(ID, player) - } - } - return null - } -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/network/container/ContainerConfigLargeMolecularAssembler.kt b/src/main/kotlin/com/muxiu1997/mxrandom/network/container/ContainerConfigLargeMolecularAssembler.kt deleted file mode 100644 index 3bf3473..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/network/container/ContainerConfigLargeMolecularAssembler.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.muxiu1997.mxrandom.network.container - -import com.muxiu1997.mxrandom.metatileentity.MTELargeMolecularAssembler -import net.minecraft.entity.player.EntityPlayer -import net.minecraft.inventory.Container - -class ContainerConfigLargeMolecularAssembler(val LMA: MTELargeMolecularAssembler) : Container() { - override fun canInteractWith(player: EntityPlayer?): Boolean { - return true - } -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/network/message/MessageCraftingFX.kt b/src/main/kotlin/com/muxiu1997/mxrandom/network/message/MessageCraftingFX.kt deleted file mode 100644 index a992b81..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/network/message/MessageCraftingFX.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.muxiu1997.mxrandom.network.message - -import appeng.api.storage.data.IAEItemStack -import appeng.util.item.AEItemStack -import com.muxiu1997.mxrandom.api.network.IMessageClientSideHandler -import com.muxiu1997.mxrandom.client.fx.CraftingFX -import cpw.mods.fml.common.network.simpleimpl.IMessage -import cpw.mods.fml.common.network.simpleimpl.MessageContext -import io.netty.buffer.ByteBuf -import kotlin.properties.Delegates -import net.minecraft.client.Minecraft - -class MessageCraftingFX : IMessage { - var x by Delegates.notNull() - var y by Delegates.notNull() - var z by Delegates.notNull() - var age by Delegates.notNull() - lateinit var itemStack: IAEItemStack - - @Suppress("unused") constructor() - - constructor(x: Int, y: Int, z: Int, age: Int, itemStack: IAEItemStack) { - this.x = x - this.y = y - this.z = z - this.age = age - this.itemStack = itemStack - } - - override fun fromBytes(buf: ByteBuf) { - x = buf.readInt() - y = buf.readInt() - z = buf.readInt() - age = buf.readInt() - itemStack = AEItemStack.loadItemStackFromPacket(buf) - } - - override fun toBytes(buf: ByteBuf) { - buf.writeInt(x) - buf.writeInt(y) - buf.writeInt(z) - buf.writeInt(age) - itemStack.writeToPacket(buf) - } - - companion object { - object Handler : IMessageClientSideHandler { - override fun handleClientSideMessage( - message: MessageCraftingFX, - ctx: MessageContext - ): IMessage? { - val fx = - CraftingFX( - Minecraft.getMinecraft().theWorld, - message.x.toDouble(), - message.y.toDouble(), - message.z.toDouble(), - message.age, - message.itemStack) - Minecraft.getMinecraft().effectRenderer.addEffect(fx) - return null - } - } - } -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/network/message/MessageSyncMetaTileEntityConfig.kt b/src/main/kotlin/com/muxiu1997/mxrandom/network/message/MessageSyncMetaTileEntityConfig.kt deleted file mode 100644 index 6bc5238..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/network/message/MessageSyncMetaTileEntityConfig.kt +++ /dev/null @@ -1,103 +0,0 @@ -package com.muxiu1997.mxrandom.network.message - -import com.muxiu1997.mxrandom.MODID -import com.muxiu1997.mxrandom.MXRandom.network -import com.muxiu1997.mxrandom.api.IConfigurableMetaTileEntity -import com.muxiu1997.mxrandom.api.network.IMessageBothSideHandler -import com.muxiu1997.mxrandom.getMetaTileEntity -import cpw.mods.fml.common.network.simpleimpl.IMessage -import cpw.mods.fml.common.network.simpleimpl.MessageContext -import io.netty.buffer.ByteBuf -import io.netty.buffer.Unpooled -import kotlin.properties.Delegates -import net.minecraft.client.Minecraft -import net.minecraftforge.common.DimensionManager - -class MessageSyncMetaTileEntityConfig : IMessage { - var x by Delegates.notNull() - var y by Delegates.notNull() - var z by Delegates.notNull() - var dimID by Delegates.notNull() - lateinit var configData: ByteBuf - var openGui by Delegates.notNull() - - @Suppress("unused") constructor() - - constructor(metaTileEntity: IConfigurableMetaTileEntity, openGui: Boolean = false) { - val baseMetaTileEntity = metaTileEntity.getBaseMetaTileEntity() - this.x = baseMetaTileEntity.xCoord - this.y = baseMetaTileEntity.yCoord.toInt() - this.z = baseMetaTileEntity.zCoord - this.dimID = baseMetaTileEntity.world.provider.dimensionId - this.configData = Unpooled.buffer() - metaTileEntity.writeConfigToBytes(this.configData) - this.openGui = openGui - } - - @Suppress("unused") - constructor(x: Int, y: Int, z: Int, dimID: Int, configData: ByteBuf, openGui: Boolean = false) { - this.x = x - this.y = y - this.z = z - this.dimID = dimID - this.configData = configData - this.openGui = openGui - } - - override fun fromBytes(buf: ByteBuf) { - x = buf.readInt() - y = buf.readInt() - z = buf.readInt() - dimID = buf.readInt() - configData = buf.readBytes(buf.readInt()) - openGui = buf.readBoolean() - } - - override fun toBytes(buf: ByteBuf) { - buf.writeInt(x) - buf.writeInt(y) - buf.writeInt(z) - buf.writeInt(dimID) - buf.writeInt(configData.readableBytes()) - buf.writeBytes(configData) - buf.writeBoolean(openGui) - } - - companion object { - object Handler : IMessageBothSideHandler { - override fun handleClientSideMessage( - message: MessageSyncMetaTileEntityConfig, - ctx: MessageContext - ): IMessage? { - val world = DimensionManager.getWorld(message.dimID) ?: return null - val metaTileEntity = - world.getMetaTileEntity(message.x, message.y, message.z) as? IConfigurableMetaTileEntity - ?: return null - metaTileEntity.readConfigFromBytes(message.configData) - if (message.openGui) { - Minecraft.getMinecraft() - .thePlayer - .openGui(MODID, 1, world, message.x, message.y, message.z) - } - return null - } - - override fun handleServerSideMessage( - message: MessageSyncMetaTileEntityConfig, - ctx: MessageContext - ): IMessage? { - val world = DimensionManager.getWorld(message.dimID) ?: return null - val metaTileEntity = - world.getMetaTileEntity(message.x, message.y, message.z) as? IConfigurableMetaTileEntity - ?: return null - val configData = message.configData.copy() - metaTileEntity.readConfigFromBytes(message.configData) - - message.openGui = false - message.configData = configData - network.sendToAll(message) - return null - } - } - } -} diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/proxy/ClientProxy.kt b/src/main/kotlin/com/muxiu1997/mxrandom/proxy/ClientProxy.kt deleted file mode 100644 index ddddf0f..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/proxy/ClientProxy.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.muxiu1997.mxrandom.proxy - -class ClientProxy : CommonProxy() diff --git a/src/main/kotlin/com/muxiu1997/mxrandom/proxy/CommonProxy.kt b/src/main/kotlin/com/muxiu1997/mxrandom/proxy/CommonProxy.kt deleted file mode 100644 index 57cd09a..0000000 --- a/src/main/kotlin/com/muxiu1997/mxrandom/proxy/CommonProxy.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.muxiu1997.mxrandom.proxy - -import com.muxiu1997.mxrandom.loader.GTMetaTileEntityLoader -import com.muxiu1997.mxrandom.loader.NetworkLoader -import com.muxiu1997.mxrandom.loader.RecipeLoader -import cpw.mods.fml.common.event.FMLInitializationEvent -import cpw.mods.fml.common.event.FMLPostInitializationEvent - -open class CommonProxy { - fun onInit(e: FMLInitializationEvent) { - GTMetaTileEntityLoader.load(e) - NetworkLoader.load(e) - } - - fun onPostInit(e: FMLPostInitializationEvent) { - RecipeLoader.load(e) - } -}