From 544d96f3bc17d361cfae9a53632b068bbf529de0 Mon Sep 17 00:00:00 2001 From: Ben Spiers Date: Wed, 1 Jan 2014 03:03:23 +0000 Subject: [PATCH] Get most of the contact process stuff working with WIP textures and such. .langs will need updating again for new things (Chemical Combiner is a provisional name though, for the time being.) --- .../mekanism/api/ChemicalCombinerInput.java | 84 +++ common/mekanism/client/ClientProxy.java | 68 +-- .../client/gui/GuiChemicalCombiner.java | 186 +++++++ common/mekanism/common/CommonProxy.java | 6 +- common/mekanism/common/Mekanism.java | 7 + common/mekanism/common/RecipeHandler.java | 50 +- .../mekanism/common/block/BlockMachine.java | 16 +- .../container/ContainerChemicalCombiner.java | 147 +++++ .../common/item/ItemBlockMachine.java | 2 +- .../TileEntityChemicalCombiner.java | 507 ++++++++++++++++++ .../tileentity/TileEntityChemicalInfuser.java | 4 +- .../mekanism/gui/GuiChemicalCombiner.png | Bin 0 -> 4522 bytes resources/assets/mekanism/lang/en_GB.lang | 7 +- resources/assets/mekanism/lang/en_US.lang | 4 + ...ulfuricGas.png => LiquidSulfurDioxide.png} | Bin ....mcmeta => LiquidSulfurDioxide.png.mcmeta} | 0 .../textures/blocks/LiquidSulfurTrioxide.png | Bin 0 -> 11231 bytes .../blocks/LiquidSulfurTrioxide.png.mcmeta | 5 + .../mekanism/textures/items/SulfurDust.png | Bin 0 -> 372 bytes 19 files changed, 1021 insertions(+), 72 deletions(-) create mode 100644 common/mekanism/api/ChemicalCombinerInput.java create mode 100644 common/mekanism/client/gui/GuiChemicalCombiner.java create mode 100644 common/mekanism/common/inventory/container/ContainerChemicalCombiner.java create mode 100644 common/mekanism/common/tileentity/TileEntityChemicalCombiner.java create mode 100644 resources/assets/mekanism/gui/GuiChemicalCombiner.png rename resources/assets/mekanism/textures/blocks/{LiquidSulfuricGas.png => LiquidSulfurDioxide.png} (100%) rename resources/assets/mekanism/textures/blocks/{LiquidSulfuricGas.png.mcmeta => LiquidSulfurDioxide.png.mcmeta} (100%) create mode 100644 resources/assets/mekanism/textures/blocks/LiquidSulfurTrioxide.png create mode 100644 resources/assets/mekanism/textures/blocks/LiquidSulfurTrioxide.png.mcmeta create mode 100644 resources/assets/mekanism/textures/items/SulfurDust.png diff --git a/common/mekanism/api/ChemicalCombinerInput.java b/common/mekanism/api/ChemicalCombinerInput.java new file mode 100644 index 000000000..abb16ce95 --- /dev/null +++ b/common/mekanism/api/ChemicalCombinerInput.java @@ -0,0 +1,84 @@ +package mekanism.api; + +import mekanism.api.gas.GasStack; +import mekanism.api.gas.GasTank; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; + +/** + * An input of one fluid and one gas for the Chemical Combiner. + * @author unpairedbracket + * + */ +public class ChemicalCombinerInput +{ + /** The gas of this chemical combiner input */ + public GasStack gas; + + /** The fluid of this chemical combiner input */ + public FluidStack fluid; + + /** + * Creates a chemical input with two defined gasses of the Chemical Infuser. + * @param gas - gas + * @param fluid - fluid + */ + public ChemicalCombinerInput(GasStack gas, FluidStack fluid) + { + this.gas = gas; + this.fluid = fluid; + } + + /** + * If this is a valid + * @return + */ + public boolean isValid() + { + return gas != null && fluid != null; + } + + /** + * Whether or not the defined input contains the same chemicals and at least the required amount of the defined chemicals as this input. + * @param input - input to check + * @return if the input meets this input's requirements + */ + public boolean meetsInput(ChemicalCombinerInput input) + { + return meets(input); + } + + /** + * Draws the needed amount of gas from each tank. + * @param gasTank - left tank to draw from + * @param fluidTank - right tank to draw from + */ + public void draw(GasTank gasTank, FluidTank fluidTank) + { + if(meets(new ChemicalCombinerInput(gasTank.getGas(), fluidTank.getFluid()))) + { + gasTank.draw(gas.amount, true); + fluidTank.drain(fluid.amount, true); + } + } + + /** + * Actual implementation of meetsInput(), performs the checks. + * @param input - input to check + * @return if the input meets this input's requirements + */ + private boolean meets(ChemicalCombinerInput input) + { + if(input == null || !input.isValid()) + { + return false; + } + + if(input.gas.getGas() != gas.getGas() || input.fluid.getFluid() != fluid.getFluid()) + { + return false; + } + + return input.gas.amount >= gas.amount && input.fluid.amount >= fluid.amount; + } +} diff --git a/common/mekanism/client/ClientProxy.java b/common/mekanism/client/ClientProxy.java index 6a7daa30a..9a6938a9a 100644 --- a/common/mekanism/client/ClientProxy.java +++ b/common/mekanism/client/ClientProxy.java @@ -4,36 +4,7 @@ package mekanism.client; import java.io.File; import java.util.HashMap; -import mekanism.client.gui.GuiChemicalInfuser; -import mekanism.client.gui.GuiChemicalInjectionChamber; -import mekanism.client.gui.GuiCombiner; -import mekanism.client.gui.GuiConfiguration; -import mekanism.client.gui.GuiCredits; -import mekanism.client.gui.GuiCrusher; -import mekanism.client.gui.GuiDictionary; -import mekanism.client.gui.GuiDigitalMiner; -import mekanism.client.gui.GuiDynamicTank; -import mekanism.client.gui.GuiElectricChest; -import mekanism.client.gui.GuiElectricPump; -import mekanism.client.gui.GuiEnergizedSmelter; -import mekanism.client.gui.GuiEnergyCube; -import mekanism.client.gui.GuiEnrichmentChamber; -import mekanism.client.gui.GuiFactory; -import mekanism.client.gui.GuiGasTank; -import mekanism.client.gui.GuiMetallurgicInfuser; -import mekanism.client.gui.GuiOsmiumCompressor; -import mekanism.client.gui.GuiChemicalOxidizer; -import mekanism.client.gui.GuiPasswordEnter; -import mekanism.client.gui.GuiPasswordModify; -import mekanism.client.gui.GuiPortableTeleporter; -import mekanism.client.gui.GuiPurificationChamber; -import mekanism.client.gui.GuiRobitCrafting; -import mekanism.client.gui.GuiRobitInventory; -import mekanism.client.gui.GuiRobitMain; -import mekanism.client.gui.GuiRobitRepair; -import mekanism.client.gui.GuiRobitSmelting; -import mekanism.client.gui.GuiRotaryCondensentrator; -import mekanism.client.gui.GuiTeleporter; +import mekanism.client.gui.*; import mekanism.client.render.MekanismRenderer; import mekanism.client.render.RenderPartTransmitter; import mekanism.client.render.RenderTickHandler; @@ -75,39 +46,7 @@ import mekanism.common.Mekanism; import mekanism.common.block.BlockMachine.MachineType; import mekanism.common.inventory.InventoryElectricChest; import mekanism.common.item.ItemPortableTeleporter; -import mekanism.common.tileentity.TileEntityAdvancedElectricMachine; -import mekanism.common.tileentity.TileEntityAdvancedFactory; -import mekanism.common.tileentity.TileEntityBin; -import mekanism.common.tileentity.TileEntityChargepad; -import mekanism.common.tileentity.TileEntityChemicalInfuser; -import mekanism.common.tileentity.TileEntityChemicalInjectionChamber; -import mekanism.common.tileentity.TileEntityCombiner; -import mekanism.common.tileentity.TileEntityCrusher; -import mekanism.common.tileentity.TileEntityDigitalMiner; -import mekanism.common.tileentity.TileEntityDiversionTransporter; -import mekanism.common.tileentity.TileEntityDynamicTank; -import mekanism.common.tileentity.TileEntityDynamicValve; -import mekanism.common.tileentity.TileEntityElectricChest; -import mekanism.common.tileentity.TileEntityElectricMachine; -import mekanism.common.tileentity.TileEntityElectricPump; -import mekanism.common.tileentity.TileEntityEliteFactory; -import mekanism.common.tileentity.TileEntityEnergizedSmelter; -import mekanism.common.tileentity.TileEntityEnergyCube; -import mekanism.common.tileentity.TileEntityEnrichmentChamber; -import mekanism.common.tileentity.TileEntityFactory; -import mekanism.common.tileentity.TileEntityGasTank; -import mekanism.common.tileentity.TileEntityLogisticalSorter; -import mekanism.common.tileentity.TileEntityLogisticalTransporter; -import mekanism.common.tileentity.TileEntityMechanicalPipe; -import mekanism.common.tileentity.TileEntityMetallurgicInfuser; -import mekanism.common.tileentity.TileEntityObsidianTNT; -import mekanism.common.tileentity.TileEntityOsmiumCompressor; -import mekanism.common.tileentity.TileEntityChemicalOxidizer; -import mekanism.common.tileentity.TileEntityPressurizedTube; -import mekanism.common.tileentity.TileEntityPurificationChamber; -import mekanism.common.tileentity.TileEntityRotaryCondensentrator; -import mekanism.common.tileentity.TileEntityTeleporter; -import mekanism.common.tileentity.TileEntityUniversalCable; +import mekanism.common.tileentity.*; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.entity.player.EntityPlayer; @@ -273,6 +212,7 @@ public class ClientProxy extends CommonProxy ClientRegistry.registerTileEntity(TileEntityTeleporter.class, "MekanismTeleporter", new RenderTeleporter()); ClientRegistry.registerTileEntity(TileEntityChemicalOxidizer.class, "ChemicalOxidizer", new RenderChemicalOxidizer()); GameRegistry.registerTileEntity(TileEntityChemicalInfuser.class, "ChemicalInfuser"); + GameRegistry.registerTileEntity(TileEntityChemicalCombiner.class, "ChemicalCombiner"); ClientRegistry.registerTileEntity(TileEntityChemicalInjectionChamber.class, "ChemicalInjectionChamber", new RenderConfigurableMachine()); } @@ -396,6 +336,8 @@ public class ClientProxy extends CommonProxy return new GuiChemicalInfuser(player.inventory, (TileEntityChemicalInfuser) tileEntity); case 31: return new GuiChemicalInjectionChamber(player.inventory, (TileEntityAdvancedElectricMachine) tileEntity); + case 32: + return new GuiChemicalCombiner(player.inventory, (TileEntityChemicalCombiner) tileEntity); } return null; diff --git a/common/mekanism/client/gui/GuiChemicalCombiner.java b/common/mekanism/client/gui/GuiChemicalCombiner.java new file mode 100644 index 000000000..4fa44311a --- /dev/null +++ b/common/mekanism/client/gui/GuiChemicalCombiner.java @@ -0,0 +1,186 @@ +package mekanism.client.gui; + +import java.util.ArrayList; + +import mekanism.api.Coord4D; +import mekanism.api.gas.GasStack; +import mekanism.client.render.MekanismRenderer; +import mekanism.common.PacketHandler; +import mekanism.common.PacketHandler.Transmission; +import mekanism.common.inventory.container.ContainerChemicalCombiner; +import mekanism.common.network.PacketTileEntity; +import mekanism.common.tileentity.TileEntityChemicalCombiner; +import mekanism.common.util.MekanismUtils; +import mekanism.common.util.MekanismUtils.ResourceType; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraftforge.fluids.FluidStack; + +import org.lwjgl.opengl.GL11; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class GuiChemicalCombiner extends GuiMekanism +{ + public TileEntityChemicalCombiner tileEntity; + + public GuiChemicalCombiner(InventoryPlayer inventory, TileEntityChemicalCombiner tentity) + { + super(tentity, new ContainerChemicalCombiner(inventory, tentity)); + tileEntity = tentity; + + guiElements.add(new GuiRedstoneControl(this, tileEntity, MekanismUtils.getResource(ResourceType.GUI, "GuiChemicalCombiner.png"))); + } + + @Override + protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) + { + int xAxis = (mouseX - (width - xSize) / 2); + int yAxis = (mouseY - (height - ySize) / 2); + + fontRenderer.drawString(MekanismUtils.localize("gui.chemicalCombiner.short"), 5, 5, 0x404040); + fontRenderer.drawString(MekanismUtils.localize("container.inventory"), 8, (ySize - 96) + 4, 0x404040); + + if(xAxis >= 116 && xAxis <= 168 && yAxis >= 76 && yAxis <= 80) + { + drawCreativeTabHoveringText(MekanismUtils.getEnergyDisplay(tileEntity.getEnergy()), xAxis, yAxis); + } + + if(xAxis >= 26 && xAxis <= 42 && yAxis >= 14 && yAxis <= 72) + { + drawCreativeTabHoveringText(tileEntity.gasTank.getGas() != null ? tileEntity.gasTank.getGas().getGas().getLocalizedName() + ": " + tileEntity.gasTank.getStored() : MekanismUtils.localize("gui.empty"), xAxis, yAxis); + } + + if(xAxis >= 134 && xAxis <= 150 && yAxis >= 14 && yAxis <= 72) + { + drawCreativeTabHoveringText(tileEntity.fluidTank.getFluid() != null ? tileEntity.fluidTank.getFluid().getFluid().getLocalizedName() + ": " + tileEntity.fluidTank.getFluidAmount() : MekanismUtils.localize("gui.empty"), xAxis, yAxis); + } + + if(xAxis >= 80 && xAxis <= 96 && yAxis >= 5 && yAxis <= 63) + { + drawCreativeTabHoveringText(tileEntity.centerTank.getGas() != null ? tileEntity.centerTank.getGas().getGas().getLocalizedName() + ": " + tileEntity.centerTank.getStored() : MekanismUtils.localize("gui.empty"), xAxis, yAxis); + } + + super.drawGuiContainerForegroundLayer(mouseX, mouseY); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTick, int mouseX, int mouseY) + { + super.drawGuiContainerBackgroundLayer(partialTick, mouseX, mouseY); + + mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiChemicalCombiner.png")); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + int guiWidth = (width - xSize) / 2; + int guiHeight = (height - ySize) / 2; + drawTexturedModalRect(guiWidth, guiHeight, 0, 0, xSize, ySize); + + int xAxis = mouseX - guiWidth; + int yAxis = mouseY - guiHeight; + + int displayInt; + + displayInt = tileEntity.getScaledEnergyLevel(52); + drawTexturedModalRect(guiWidth + 116, guiHeight + 76, 176, 0, displayInt, 4); + + if(tileEntity.isActive) + { + drawTexturedModalRect(guiWidth + 47, guiHeight + 39, 176, 71, 28, 8); + drawTexturedModalRect(guiWidth + 101, guiHeight + 39, 176, 63, 28, 8); + } + + if(tileEntity.getScaledGasLevel(58) > 0) + { + displayGauge(26, 14, tileEntity.getScaledGasLevel(58), null, tileEntity.gasTank.getGas()); + } + + if(tileEntity.getScaledFluidLevel(58) > 0) + { + displayGauge(134, 14, tileEntity.getScaledFluidLevel(58), tileEntity.fluidTank.getFluid(), null); + } + + if(tileEntity.getScaledOutputLevel(58) > 0) + { + displayGauge(80, 5, tileEntity.getScaledOutputLevel(58), null, tileEntity.centerTank.getGas()); + } + } + + @Override + protected void mouseClicked(int x, int y, int button) + { + super.mouseClicked(x, y, button); + + if(button == 0) + { + int xAxis = (x - (width - xSize) / 2); + int yAxis = (y - (height - ySize) / 2); + + if(xAxis > 44 && xAxis < 62 && yAxis > 13 && yAxis < 21) + { + ArrayList data = new ArrayList(); + data.add(0); + + PacketHandler.sendPacket(Transmission.SERVER, new PacketTileEntity().setParams(Coord4D.get(tileEntity), data)); + mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F); + } + else if(xAxis > 114 && xAxis < 132 && yAxis > 13 && yAxis < 21) + { + ArrayList data = new ArrayList(); + data.add(1); + + PacketHandler.sendPacket(Transmission.SERVER, new PacketTileEntity().setParams(Coord4D.get(tileEntity), data)); + mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F); + } + } + } + + public void displayGauge(int xPos, int yPos, int scale, FluidStack fluid, GasStack gas) + { + if(fluid == null && gas == null) + { + return; + } + + int guiWidth = (width - xSize) / 2; + int guiHeight = (height - ySize) / 2; + + int start = 0; + + while(true) + { + int renderRemaining = 0; + + if(scale > 16) + { + renderRemaining = 16; + scale -= 16; + } + else { + renderRemaining = scale; + scale = 0; + } + + mc.renderEngine.bindTexture(MekanismRenderer.getBlocksTexture()); + + if(fluid != null) + { + drawTexturedModelRectFromIcon(guiWidth + xPos, guiHeight + yPos + 58 - renderRemaining - start, fluid.getFluid().getIcon(), 16, 16 - (16 - renderRemaining)); + } + else if(gas != null) + { + drawTexturedModelRectFromIcon(guiWidth + xPos, guiHeight + yPos + 58 - renderRemaining - start, gas.getGas().getIcon(), 16, 16 - (16 - renderRemaining)); + } + + start+=16; + + if(renderRemaining == 0 || scale == 0) + { + break; + } + } + + mc.renderEngine.bindTexture(MekanismUtils.getResource(ResourceType.GUI, "GuiChemicalCombiner.png")); + drawTexturedModalRect(guiWidth + xPos, guiHeight + yPos, 176, 4, 16, 59); + } +} \ No newline at end of file diff --git a/common/mekanism/common/CommonProxy.java b/common/mekanism/common/CommonProxy.java index eabead38a..cc98a0c8c 100644 --- a/common/mekanism/common/CommonProxy.java +++ b/common/mekanism/common/CommonProxy.java @@ -58,12 +58,13 @@ public class CommonProxy GameRegistry.registerTileEntity(TileEntityTeleporter.class, "MekanismTeleporter"); GameRegistry.registerTileEntity(TileEntityChemicalOxidizer.class, "ChemicalOxidizer"); GameRegistry.registerTileEntity(TileEntityChemicalInfuser.class, "ChemicalInfuser"); + GameRegistry.registerTileEntity(TileEntityChemicalCombiner.class, "ChemicalCombiner"); GameRegistry.registerTileEntity(TileEntityChemicalInjectionChamber.class, "ChemicalInjectionChamber"); } /** * Registers a client-side sound, assigned to a TileEntity. - * @param tileEntity - TileEntity who is registering the sound + * @param obj - TileEntity who is registering the sound */ public void registerSound(Object obj) {} @@ -157,6 +158,7 @@ public class CommonProxy Mekanism.rotaryCondensentratorUsage = Mekanism.configuration.get("usage", "RotaryCondensentratorUsage", 50D).getDouble(50D); Mekanism.oxidationChamberUsage = Mekanism.configuration.get("usage", "OxidationChamberUsage", 100D).getDouble(100D); Mekanism.chemicalInfuserUsage = Mekanism.configuration.get("usage", "ChemicalInfuserUsage", 100D).getDouble(100D); + Mekanism.chemicalCombinerUsage = Mekanism.configuration.get("usage", "ChemicalCombinerUsage", 100D).getDouble(100D); Mekanism.chemicalInjectionChamberUsage = Mekanism.configuration.get("usage", "ChemicalInjectionChamberUsage", 200D).getDouble(200D); Mekanism.configuration.save(); } @@ -295,6 +297,8 @@ public class CommonProxy return new ContainerChemicalInfuser(player.inventory, (TileEntityChemicalInfuser)tileEntity); case 31: return new ContainerAdvancedElectricMachine(player.inventory, (TileEntityAdvancedElectricMachine)tileEntity); + case 32: + return new ContainerChemicalCombiner(player.inventory, (TileEntityChemicalCombiner)tileEntity); } return null; diff --git a/common/mekanism/common/Mekanism.java b/common/mekanism/common/Mekanism.java index 6a991aa0b..32f0079c9 100644 --- a/common/mekanism/common/Mekanism.java +++ b/common/mekanism/common/Mekanism.java @@ -10,6 +10,7 @@ import java.util.Map; import java.util.Set; import java.util.logging.Logger; +import mekanism.api.ChemicalCombinerInput; import mekanism.api.ChemicalInput; import mekanism.api.Coord4D; import mekanism.api.EnumColor; @@ -110,6 +111,8 @@ import net.minecraftforge.common.Configuration; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.ForgeSubscribe; import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.oredict.OreDictionary; import net.minecraftforge.oredict.ShapelessOreRecipe; import rebelkeithy.mods.metallurgy.api.IOreInfo; @@ -290,6 +293,7 @@ public class Mekanism public static double rotaryCondensentratorUsage; public static double oxidationChamberUsage; public static double chemicalInfuserUsage; + public static double chemicalCombinerUsage; public static double chemicalInjectionChamberUsage; /** @@ -618,6 +622,9 @@ public class Mekanism //Chemical Infuser Recipes RecipeHandler.addChemicalInfuserRecipe(new ChemicalInput(new GasStack(GasRegistry.getGas("oxygen"), 1), new GasStack(GasRegistry.getGas("sulfurDioxideGas"), 2)), new GasStack(GasRegistry.getGas("sulfurTrioxideGas"), 2)); + + //Chemical Combiner Recipes + RecipeHandler.addChemicalCombinerRecipe(new ChemicalCombinerInput(new GasStack(GasRegistry.getGas("sulfurTrioxideGas"), 1), new FluidStack(FluidRegistry.getFluid("water"), 1)), new GasStack(GasRegistry.getGas("sulfuricAcid"), 1)); //Infuse objects InfuseRegistry.registerInfuseObject(new ItemStack(Item.coal, 1, 0), new InfuseObject(InfuseRegistry.get("CARBON"), 10)); diff --git a/common/mekanism/common/RecipeHandler.java b/common/mekanism/common/RecipeHandler.java index 3eaff1b4a..9f0d32434 100644 --- a/common/mekanism/common/RecipeHandler.java +++ b/common/mekanism/common/RecipeHandler.java @@ -3,6 +3,7 @@ package mekanism.common; import java.util.HashMap; import java.util.Map; +import mekanism.api.ChemicalCombinerInput; import mekanism.api.ChemicalInput; import mekanism.api.gas.GasStack; import mekanism.api.gas.GasTank; @@ -10,6 +11,7 @@ import mekanism.api.infuse.InfusionInput; import mekanism.api.infuse.InfusionOutput; import mekanism.common.util.StackUtils; import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidTank; /** * Class used to handle machine recipes. This is used for both adding recipes and checking outputs. @@ -93,6 +95,15 @@ public final class RecipeHandler Recipe.CHEMICAL_INFUSER.put(input, output); } + /** + * Add a Chemical Combiner recipe + * @param input - input ChemicalCombinerInput + */ + public static void addChemicalCombinerRecipe(ChemicalCombinerInput input, GasStack output) + { + Recipe.CHEMICAL_COMBINER.put(input, output); + } + /** * Add a Chemical Oxidizer recipe. * @param input - input ItemStack @@ -149,7 +160,9 @@ public final class RecipeHandler /** * Gets the GasStack of the ChemicalInput in the parameters. - * @param input - input ChemicalInput + * @param leftTank - first GasTank + * @param rightTank - second GasTank + * @param doRemove - actually remove the gases * @return output GasStack */ public static GasStack getChemicalInfuserOutput(GasTank leftTank, GasTank rightTank, boolean doRemove) @@ -179,6 +192,40 @@ public final class RecipeHandler return null; } + /** + * Gets the GasStack of the ChemicalCombinerInput in the parameters. + * @param gasTank - GasTank containing the gas to use + * @param fluidTank - FluidTank containing the fluid to use + * @param doRemove - actually drain the tanks + * @return output - GasStack returned + */ + public static GasStack getChemicalCombinerOutput(GasTank gasTank, FluidTank fluidTank, boolean doRemove) + { + ChemicalCombinerInput input = new ChemicalCombinerInput(gasTank.getGas(), fluidTank.getFluid()); + + if(input.isValid()) + { + HashMap recipes = Recipe.CHEMICAL_COMBINER.get(); + + for(Map.Entry entry : recipes.entrySet()) + { + ChemicalCombinerInput key = (ChemicalCombinerInput)entry.getKey(); + + if(key.meetsInput(input)) + { + if(doRemove) + { + key.draw(gasTank, fluidTank); + } + + return entry.getValue().copy(); + } + } + } + + return null; + } + /** * Gets the InfusionOutput of the ItemStack in the parameters. * @param itemstack - input ItemStack @@ -249,6 +296,7 @@ public final class RecipeHandler PURIFICATION_CHAMBER(new HashMap()), METALLURGIC_INFUSER(new HashMap()), CHEMICAL_INFUSER(new HashMap()), + CHEMICAL_COMBINER(new HashMap()), CHEMICAL_OXIDIZER(new HashMap()), CHEMICAL_INJECTION_CHAMBER(new HashMap()); diff --git a/common/mekanism/common/block/BlockMachine.java b/common/mekanism/common/block/BlockMachine.java index 13cbb1ea6..8a38f62df 100644 --- a/common/mekanism/common/block/BlockMachine.java +++ b/common/mekanism/common/block/BlockMachine.java @@ -138,6 +138,9 @@ public class BlockMachine extends BlockContainer implements ISpecialBounds icons[3][0] = register.registerIcon("mekanism:ChemicalInjectionChamberFrontOff"); icons[3][1] = register.registerIcon("mekanism:ChemicalInjectionChamberFrontOn"); icons[3][2] = register.registerIcon("mekanism:SteelCasing"); + icons[4][0] = register.registerIcon("mekanism:ChemicalInjectionChamberFrontOff"); + icons[4][1] = register.registerIcon("mekanism:ChemicalInjectionChamberFrontOn"); + icons[4][2] = register.registerIcon("mekanism:SteelCasing"); } } @@ -413,6 +416,16 @@ public class BlockMachine extends BlockContainer implements ISpecialBounds return icons[3][2]; } } + else if(meta == 4) + { + if(side == 3) + { + return icons[4][0]; + } + else { + return icons[4][2]; + } + } } return null; @@ -536,7 +549,7 @@ public class BlockMachine extends BlockContainer implements ISpecialBounds } else if(blockID == Mekanism.machineBlock2ID) { - if(metadata == 2 || metadata == 3) + if(metadata == 2 || metadata == 3 || metadata == 4) { if(side == tileEntity.facing) { @@ -1078,6 +1091,7 @@ public class BlockMachine extends BlockContainer implements ISpecialBounds ROTARY_CONDENSENTRATOR(Mekanism.machineBlock2ID, 0, "RotaryCondensentrator", 7, 20000, TileEntityRotaryCondensentrator.class, true), CHEMICAL_OXIDIZER(Mekanism.machineBlock2ID, 1, "ChemicalOxidizer", 29, 20000, TileEntityChemicalOxidizer.class, true), CHEMICAL_INFUSER(Mekanism.machineBlock2ID, 2, "ChemicalInfuser", 30, 20000, TileEntityChemicalInfuser.class, false), + CHEMICAL_COMBINER(Mekanism.machineBlock2ID, 4, "ChemicalCombiner", 32, 20000, TileEntityChemicalCombiner.class, false), CHEMICAL_INJECTION_CHAMBER(Mekanism.machineBlock2ID, 3, "ChemicalInjectionChamber", 31, Mekanism.chemicalInjectionChamberUsage*400, TileEntityChemicalInjectionChamber.class, false); public int typeId; diff --git a/common/mekanism/common/inventory/container/ContainerChemicalCombiner.java b/common/mekanism/common/inventory/container/ContainerChemicalCombiner.java new file mode 100644 index 000000000..86e8a48b1 --- /dev/null +++ b/common/mekanism/common/inventory/container/ContainerChemicalCombiner.java @@ -0,0 +1,147 @@ +package mekanism.common.inventory.container; + +import mekanism.api.gas.IGasItem; +import mekanism.common.inventory.slot.SlotEnergy.SlotDischarge; +import mekanism.common.inventory.slot.SlotStorageTank; +import mekanism.common.item.ItemMachineUpgrade; +import mekanism.common.tileentity.TileEntityChemicalCombiner; +import mekanism.common.tileentity.TileEntityChemicalInfuser; +import mekanism.common.util.ChargeUtils; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +public class ContainerChemicalCombiner extends Container +{ + private TileEntityChemicalCombiner tileEntity; + + public ContainerChemicalCombiner(InventoryPlayer inventory, TileEntityChemicalCombiner tentity) + { + tileEntity = tentity; + addSlotToContainer(new SlotStorageTank(tentity, null, true, 0, 5, 56)); + addSlotToContainer(new SlotStorageTank(tentity, null, true, 1, 155, 56)); + addSlotToContainer(new Slot(tentity, 2, 80, 65)); + addSlotToContainer(new SlotDischarge(tentity, 3, 155, 5)); + + int slotX; + + for(slotX = 0; slotX < 3; slotX++) + { + for(int slotY = 0; slotY < 9; slotY++) + { + addSlotToContainer(new Slot(inventory, slotY + slotX * 9 + 9, 8 + slotY * 18, 84 + slotX * 18)); + } + } + + for(slotX = 0; slotX < 9; ++slotX) + { + addSlotToContainer(new Slot(inventory, slotX, 8 + slotX * 18, 142)); + } + + tileEntity.open(inventory.player); + tileEntity.openChest(); + } + + @Override + public void onContainerClosed(EntityPlayer entityplayer) + { + super.onContainerClosed(entityplayer); + + tileEntity.close(entityplayer); + tileEntity.closeChest(); + } + + @Override + public boolean canInteractWith(EntityPlayer entityplayer) + { + return tileEntity.isUseableByPlayer(entityplayer); + } + + @Override + public ItemStack transferStackInSlot(EntityPlayer player, int slotID) + { + ItemStack stack = null; + Slot currentSlot = (Slot)inventorySlots.get(slotID); + + if(currentSlot != null && currentSlot.getHasStack()) + { + ItemStack slotStack = currentSlot.getStack(); + stack = slotStack.copy(); + + if(ChargeUtils.canBeDischarged(slotStack)) + { + if(slotID != 3) + { + if(!mergeItemStack(slotStack, 3, 4, false)) + { + return null; + } + } + else if(slotID == 3) + { + if(!mergeItemStack(slotStack, 4, inventorySlots.size(), true)) + { + return null; + } + } + } + else if(slotStack.getItem() instanceof IGasItem) + { + if(slotID != 0 && slotID != 1 && slotID != 2) + { + if(!mergeItemStack(slotStack, 0, 3, false)) + { + return null; + } + } + else { + if(!mergeItemStack(slotStack, 5, inventorySlots.size(), true)) + { + return null; + } + } + } + else { + if(slotID >= 4 && slotID <= 30) + { + if(!mergeItemStack(slotStack, 31, inventorySlots.size(), false)) + { + return null; + } + } + else if(slotID > 30) + { + if(!mergeItemStack(slotStack, 4, 30, false)) + { + return null; + } + } + else { + if(!mergeItemStack(slotStack, 4, inventorySlots.size(), true)) + { + return null; + } + } + } + + if(slotStack.stackSize == 0) + { + currentSlot.putStack((ItemStack)null); + } + else { + currentSlot.onSlotChanged(); + } + + if(slotStack.stackSize == stack.stackSize) + { + return null; + } + + currentSlot.onPickupFromSlot(player, slotStack); + } + + return stack; + } +} diff --git a/common/mekanism/common/item/ItemBlockMachine.java b/common/mekanism/common/item/ItemBlockMachine.java index 8b1a73fe9..edc589ba8 100644 --- a/common/mekanism/common/item/ItemBlockMachine.java +++ b/common/mekanism/common/item/ItemBlockMachine.java @@ -504,7 +504,7 @@ public class ItemBlockMachine extends ItemBlock implements IEnergizedItem, ISpec MachineType type = MachineType.get((ItemStack)data[0]); if(type != MachineType.TELEPORTER && type != MachineType.ELECTRIC_PUMP && type != MachineType.ELECTRIC_CHEST && type != MachineType.CHARGEPAD && type != MachineType.LOGISTICAL_SORTER && - type != MachineType.ROTARY_CONDENSENTRATOR && type != MachineType.CHEMICAL_OXIDIZER && type != MachineType.CHEMICAL_INFUSER) + type != MachineType.ROTARY_CONDENSENTRATOR && type != MachineType.CHEMICAL_OXIDIZER && type != MachineType.CHEMICAL_INFUSER && type != MachineType.CHEMICAL_COMBINER) { return true; } diff --git a/common/mekanism/common/tileentity/TileEntityChemicalCombiner.java b/common/mekanism/common/tileentity/TileEntityChemicalCombiner.java new file mode 100644 index 000000000..13815af01 --- /dev/null +++ b/common/mekanism/common/tileentity/TileEntityChemicalCombiner.java @@ -0,0 +1,507 @@ +package mekanism.common.tileentity; + +import java.util.ArrayList; + +import mekanism.api.Coord4D; +import mekanism.api.gas.Gas; +import mekanism.api.gas.GasRegistry; +import mekanism.api.gas.GasStack; +import mekanism.api.gas.GasTank; +import mekanism.api.gas.GasTransmission; +import mekanism.api.gas.IGasHandler; +import mekanism.api.gas.IGasItem; +import mekanism.api.gas.ITubeConnection; +import mekanism.common.*; +import mekanism.common.PacketHandler.Transmission; +import mekanism.common.block.BlockMachine.MachineType; +import mekanism.common.network.PacketTileEntity; +import mekanism.common.util.ChargeUtils; +import mekanism.common.util.InventoryUtils; +import mekanism.common.util.MekanismUtils; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; + +import com.google.common.io.ByteArrayDataInput; +import net.minecraftforge.fluids.*; + +public class TileEntityChemicalCombiner extends TileEntityElectricBlock implements IActiveState, IGasHandler, ITubeConnection, IRedstoneControl, IFluidHandler +{ + public GasTank gasTank = new GasTank(MAX); + public FluidTank fluidTank = new FluidTank(MAX); + public GasTank centerTank = new GasTank(MAX); + + public static final int MAX = 10000; + + public int updateDelay; + + public int gasOutput = 16; + + public boolean isActive; + + public boolean clientActive; + + public double prevEnergy; + + public final double ENERGY_USAGE = Mekanism.chemicalCombinerUsage; + + /** This machine's current RedstoneControl type. */ + public RedstoneControl controlType = RedstoneControl.DISABLED; + + public TileEntityChemicalCombiner() + { + super("ChemicalCombiner", MachineType.CHEMICAL_COMBINER.baseEnergy); + inventory = new ItemStack[4]; + } + + @Override + public void onUpdate() + { + if(worldObj.isRemote) + { + if(updateDelay > 0) + { + updateDelay--; + + if(updateDelay == 0 && clientActive != isActive) + { + isActive = clientActive; + MekanismUtils.updateBlock(worldObj, xCoord, yCoord, zCoord); + } + } + } + + if(!worldObj.isRemote) + { + if(updateDelay > 0) + { + updateDelay--; + + if(updateDelay == 0 && clientActive != isActive) + { + PacketHandler.sendPacket(Transmission.ALL_CLIENTS, new PacketTileEntity().setParams(Coord4D.get(this), getNetworkedData(new ArrayList()))); + } + } + + ChargeUtils.discharge(3, this); + + if(inventory[0] != null && (gasTank.getGas() == null || gasTank.getStored() < gasTank.getMaxGas())) + { + gasTank.receive(GasTransmission.removeGas(inventory[0], null, gasTank.getNeeded()), true); + } + + if(inventory[1] != null && (fluidTank.getFluid() == null || fluidTank.getFluidAmount() < fluidTank.getCapacity())) + { + if(inventory[1].getItem() instanceof IFluidContainerItem) + { + fluidTank.fill(((IFluidContainerItem) inventory[1].getItem()).drain(inventory[1], fluidTank.getCapacity()-fluidTank.getFluidAmount(), true), true); + } + else if(FluidContainerRegistry.isFilledContainer(inventory[1]) && FluidContainerRegistry.getFluidForFilledItem(inventory[1]).equals(fluidTank.getFluid())) + { + fluidTank.fill(FluidContainerRegistry.getFluidForFilledItem(inventory[1]), true); + inventory[1] = inventory[1].getItem().getContainerItemStack(inventory[1]); + } + } + + if(inventory[2] != null && centerTank.getGas() != null) + { + centerTank.draw(GasTransmission.addGas(inventory[2], centerTank.getGas()), true); + } + + if(canOperate() && getEnergy() >= ENERGY_USAGE && MekanismUtils.canFunction(this)) + { + setActive(true); + GasStack stack = RecipeHandler.getChemicalCombinerOutput(gasTank, fluidTank, true); + + centerTank.receive(stack, true); + + setEnergy(getEnergy() - ENERGY_USAGE); + } + else { + if(prevEnergy >= getEnergy()) + { + setActive(false); + } + } + + if(centerTank.getGas() != null) + { + GasStack toSend = new GasStack(centerTank.getGas().getGas(), Math.min(centerTank.getStored(), gasOutput)); + centerTank.draw(GasTransmission.emitGasToNetwork(toSend, this, ForgeDirection.getOrientation(facing)), true); + + TileEntity tileEntity = Coord4D.get(this).getFromSide(ForgeDirection.getOrientation(facing)).getTileEntity(worldObj); + + if(tileEntity instanceof IGasHandler) + { + if(((IGasHandler)tileEntity).canReceiveGas(ForgeDirection.getOrientation(facing).getOpposite(), centerTank.getGas().getGas())) + { + centerTank.draw(((IGasHandler)tileEntity).receiveGas(ForgeDirection.getOrientation(facing).getOpposite(), toSend), true); + } + } + } + + prevEnergy = getEnergy(); + } + } + + public boolean canOperate() + { + if(gasTank.getGas() == null || fluidTank.getFluid() == null || centerTank.getNeeded() == 0) + { + return false; + } + + GasStack out = RecipeHandler.getChemicalCombinerOutput(gasTank, fluidTank, false); + + if(out == null) + { + return false; + } + + if(centerTank.getNeeded() < out.amount) + { + return false; + } + + return true; + } + + @Override + public void handlePacketData(ByteArrayDataInput dataStream) + { + if(!worldObj.isRemote) + { + int type = dataStream.readInt(); + + if(type == 0) + { + gasTank.setGas(null); + } + else if(type == 1) + { + fluidTank.setFluid(null); + } + + for(EntityPlayer player : playersUsing) + { + PacketHandler.sendPacket(Transmission.SINGLE_CLIENT, new PacketTileEntity().setParams(Coord4D.get(this), getNetworkedData(new ArrayList())), player); + } + + return; + } + + super.handlePacketData(dataStream); + + isActive = dataStream.readBoolean(); + controlType = RedstoneControl.values()[dataStream.readInt()]; + + if(dataStream.readBoolean()) + { + gasTank.setGas(new GasStack(GasRegistry.getGas(dataStream.readInt()), dataStream.readInt())); + } + else { + gasTank.setGas(null); + } + + if(dataStream.readBoolean()) + { + fluidTank.setFluid(new FluidStack(FluidRegistry.getFluid(dataStream.readInt()), dataStream.readInt())); + } + else { + fluidTank.setFluid(null); + } + + if(dataStream.readBoolean()) + { + centerTank.setGas(new GasStack(GasRegistry.getGas(dataStream.readInt()), dataStream.readInt())); + } + else { + centerTank.setGas(null); + } + + + MekanismUtils.updateBlock(worldObj, xCoord, yCoord, zCoord); + } + + @Override + public ArrayList getNetworkedData(ArrayList data) + { + super.getNetworkedData(data); + + data.add(isActive); + data.add(controlType.ordinal()); + + if(gasTank.getGas() != null) + { + data.add(true); + data.add(gasTank.getGas().getGas().getID()); + data.add(gasTank.getStored()); + } + else { + data.add(false); + } + + if(fluidTank.getFluid() != null) + { + data.add(true); + data.add(fluidTank.getFluid().getFluid().getID()); + data.add(fluidTank.getFluidAmount()); + } + else { + data.add(false); + } + + if(centerTank.getGas() != null) + { + data.add(true); + data.add(centerTank.getGas().getGas().getID()); + data.add(centerTank.getStored()); + } + else { + data.add(false); + } + + return data; + } + + @Override + public void readFromNBT(NBTTagCompound nbtTags) + { + super.readFromNBT(nbtTags); + + isActive = nbtTags.getBoolean("isActive"); + controlType = RedstoneControl.values()[nbtTags.getInteger("controlType")]; + + gasTank.read(nbtTags.getCompoundTag("gasTank")); + fluidTank.readFromNBT(nbtTags.getCompoundTag("fluidTank")); + centerTank.read(nbtTags.getCompoundTag("centerTank")); + } + + @Override + public void writeToNBT(NBTTagCompound nbtTags) + { + super.writeToNBT(nbtTags); + + nbtTags.setBoolean("isActive", isActive); + nbtTags.setInteger("controlType", controlType.ordinal()); + + nbtTags.setCompoundTag("gasTank", gasTank.write(new NBTTagCompound())); + nbtTags.setCompoundTag("fluidTank", fluidTank.writeToNBT(new NBTTagCompound())); + nbtTags.setCompoundTag("centerTank", centerTank.write(new NBTTagCompound())); + } + + @Override + public boolean canSetFacing(int i) + { + return i != 0 && i != 1; + } + + public GasTank getGasTank(ForgeDirection side) + { + if(side == MekanismUtils.getLeft(facing)) + { + return gasTank; + } + else if(side == ForgeDirection.getOrientation(facing)) + { + return centerTank; + } + + return null; + } + + public FluidTank getFluidTank(ForgeDirection side) + { + if(side == MekanismUtils.getRight(facing)) + { + return fluidTank; + } + + return null; + } + + public int getScaledGasLevel(int i) + { + return gasTank != null ? gasTank.getStored()*i / MAX : 0; + } + + public int getScaledFluidLevel(int i) + { + return fluidTank != null ? fluidTank.getFluidAmount()*i / MAX : 0; + } + + public int getScaledOutputLevel(int i) + { + return centerTank != null ? centerTank.getStored()*i / MAX : 0; + } + + @Override + public void setActive(boolean active) + { + isActive = active; + + if(clientActive != active && updateDelay == 0) + { + PacketHandler.sendPacket(Transmission.ALL_CLIENTS, new PacketTileEntity().setParams(Coord4D.get(this), getNetworkedData(new ArrayList()))); + + updateDelay = 10; + clientActive = active; + } + } + + @Override + public boolean getActive() + { + return isActive; + } + + @Override + public boolean renderUpdate() + { + return false; + } + + @Override + public boolean lightUpdate() + { + return true; + } + + @Override + public boolean canTubeConnect(ForgeDirection side) + { + return side == MekanismUtils.getLeft(facing) || side == MekanismUtils.getRight(facing) || side == ForgeDirection.getOrientation(facing); + } + + @Override + public boolean canReceiveGas(ForgeDirection side, Gas type) + { + return getGasTank(side) != null && getGasTank(side) != centerTank ? getGasTank(side).canReceive(type) : false; + } + + @Override + public RedstoneControl getControlType() + { + return controlType; + } + + @Override + public void setControlType(RedstoneControl type) + { + controlType = type; + MekanismUtils.saveChunk(this); + } + + @Override + public int receiveGas(ForgeDirection side, GasStack stack) + { + if(canReceiveGas(side, stack != null ? stack.getGas() : null)) + { + return getGasTank(side).receive(stack, true); + } + + return 0; + } + + @Override + public GasStack drawGas(ForgeDirection side, int amount) + { + if(canDrawGas(side, null)) + { + return getGasTank(side).draw(amount, true); + } + + return null; + } + + @Override + public boolean canDrawGas(ForgeDirection side, Gas type) + { + return getGasTank(side) != null && getGasTank(side) == centerTank ? getGasTank(side).canDraw(type) : false; + } + + @Override + public boolean isItemValidForSlot(int slotID, ItemStack itemstack) + { + if(slotID == 3) + { + return ChargeUtils.canBeDischarged(itemstack); + } + + return false; + } + + @Override + public boolean canExtractItem(int slotID, ItemStack itemstack, int side) + { + if(slotID == 0) + { + return itemstack != null && itemstack.getItem() instanceof IGasItem && ((IGasItem)itemstack.getItem()).canReceiveGas(itemstack, null); + } + if(slotID == 1) + { + return itemstack != null && itemstack.getItem() instanceof IGasItem && ((IGasItem)itemstack.getItem()).canProvideGas(itemstack, null); + } + + return false; + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) + { + if(side == MekanismUtils.getLeft(facing).ordinal()) + { + return new int[] {0}; + } + else if(side == facing) + { + return new int[] {1}; + } + else if(side == MekanismUtils.getRight(facing).ordinal()) + { + return new int[] {2}; + } + else if(side == 0 || side == 1) + { + return new int[3]; + } + + return InventoryUtils.EMPTY; + } + + @Override + public int fill(ForgeDirection side, FluidStack resource, boolean doFill) { + return getFluidTank(side) == null ? 0 : getFluidTank(side).fill(resource, doFill); + } + + @Override + public FluidStack drain(ForgeDirection side, FluidStack resource, boolean doDrain) { + return getFluidTank(side) == null && getFluidTank(side).getFluid().isFluidEqual(resource) ? null : getFluidTank(side).drain(resource.amount, doDrain); + } + + @Override + public FluidStack drain(ForgeDirection side, int maxDrain, boolean doDrain) { + return getFluidTank(side) == null ? null : getFluidTank(side).drain(maxDrain, doDrain); + } + + @Override + public boolean canFill(ForgeDirection side, Fluid fluid) { + return getFluidTank(side) != null && (getFluidTank(side).getFluid() == null || getFluidTank(side).getFluid().getFluid() == fluid); + } + + @Override + public boolean canDrain(ForgeDirection side, Fluid fluid) { + return getFluidTank(side) != null && getFluidTank(side).getFluid().getFluid() == fluid; + } + + @Override + public FluidTankInfo[] getTankInfo(ForgeDirection side) { + if(getFluidTank(side) == null) + { + return new FluidTankInfo[0]; + } + return new FluidTankInfo[] {new FluidTankInfo(getFluidTank(side))}; + } +} diff --git a/common/mekanism/common/tileentity/TileEntityChemicalInfuser.java b/common/mekanism/common/tileentity/TileEntityChemicalInfuser.java index d33c3be9a..eb7d6670e 100644 --- a/common/mekanism/common/tileentity/TileEntityChemicalInfuser.java +++ b/common/mekanism/common/tileentity/TileEntityChemicalInfuser.java @@ -314,12 +314,12 @@ public class TileEntityChemicalInfuser extends TileEntityElectricBlock implement public int getScaledRightGasLevel(int i) { - return leftTank != null ? rightTank.getStored()*i / MAX_GAS : 0; + return rightTank != null ? rightTank.getStored()*i / MAX_GAS : 0; } public int getScaledCenterGasLevel(int i) { - return leftTank != null ? centerTank.getStored()*i / MAX_GAS : 0; + return centerTank != null ? centerTank.getStored()*i / MAX_GAS : 0; } @Override diff --git a/resources/assets/mekanism/gui/GuiChemicalCombiner.png b/resources/assets/mekanism/gui/GuiChemicalCombiner.png new file mode 100644 index 0000000000000000000000000000000000000000..4d851e5472775bc1cb6ce5820f6e094a21e4fbfe GIT binary patch literal 4522 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 JPDHLkV1lJzUm^ei literal 0 HcmV?d00001 diff --git a/resources/assets/mekanism/textures/blocks/LiquidSulfurTrioxide.png.mcmeta b/resources/assets/mekanism/textures/blocks/LiquidSulfurTrioxide.png.mcmeta new file mode 100644 index 000000000..4b721e09a --- /dev/null +++ b/resources/assets/mekanism/textures/blocks/LiquidSulfurTrioxide.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 2 + } +} diff --git a/resources/assets/mekanism/textures/items/SulfurDust.png b/resources/assets/mekanism/textures/items/SulfurDust.png new file mode 100644 index 0000000000000000000000000000000000000000..05e2296166410420d1dd7b78fe263bc2cd9dc714 GIT binary patch literal 372 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&kwQk&)3_Y{iU~B@7IVjGiuzArXg@|NQ@Nf7pRZt&Ndw zF`q;!1NTlT(^S`hP3ONJ&zEp_<2X>W@BbFHu)-kcq!%p=XWHA(R~s7u!JnVS{f!{d zeHu(Bp6%P6(t4z!ok4lwE{5{Qo8iOq0I$Cc#-yTrAA(;e4A);nn>|kH$)ZjLG5MZp5>;s3G7q zyRA#X)AFQfuV#A|j#dsUi6UL4V;A>5>?mhoIJ3B>qgT1@958$sJYD@<);T3K0RWG@ Bist|T literal 0 HcmV?d00001