From 5f084882682080258b46a5eb649a9eaa8495ae74 Mon Sep 17 00:00:00 2001 From: Boblet Date: Mon, 16 Jun 2025 16:17:31 +0200 Subject: [PATCH] d'oh --- changelog | 7 +- src/main/java/com/hbm/blocks/ModBlocks.java | 3 + .../com/hbm/blocks/generic/BlockReeds.java | 3 +- .../machine/MachineChemicalFactory.java | 45 +++ .../inventory/container/ContainerBase.java | 15 +- .../container/ContainerCrateBase.java | 8 +- .../ContainerMachineChemicalFactory.java | 77 +++++ .../hbm/inventory/fluid/tank/FluidTank.java | 6 + .../gui/GUIMachineChemicalFactory.java | 132 ++++++++ src/main/java/com/hbm/main/ClientProxy.java | 2 + .../java/com/hbm/main/ResourceManager.java | 2 + .../hbm/module/ModuleMachineChemplant.java | 4 +- .../tileentity/RenderChemicalFactory.java | 71 +++++ .../java/com/hbm/tileentity/TileMappings.java | 1 + .../TileEntityMachineChemicalFactory.java | 293 ++++++++++++++++++ .../TileEntityMachineChemicalPlant.java | 6 +- .../machine/TileEntityMachineTurbineGas.java | 7 +- .../gui/processing/gui_chemical_factory.png | Bin 3840 -> 3531 bytes .../hbm/textures/items/billet_yharonite.png | Bin 352 -> 312 bytes .../textures/models/machines/radar_base.png | Bin 1006 -> 947 bytes .../textures/models/machines/radar_dish.png | Bin 1502 -> 1407 bytes 21 files changed, 669 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/hbm/blocks/machine/MachineChemicalFactory.java create mode 100644 src/main/java/com/hbm/inventory/container/ContainerMachineChemicalFactory.java create mode 100644 src/main/java/com/hbm/inventory/gui/GUIMachineChemicalFactory.java create mode 100644 src/main/java/com/hbm/render/tileentity/RenderChemicalFactory.java create mode 100644 src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalFactory.java diff --git a/changelog b/changelog index c802deca0..b84be97b5 100644 --- a/changelog +++ b/changelog @@ -3,6 +3,9 @@ * Compressed biomass now has a nice cube shape * The new chemical plant's indicator lights are now functional * The new chemical plant can now use upgrades +* Reeds now drop sticks when broken +* Switching the recipe in the new chemplant now annihilates residual fluid that is not overwritten by the new recipe + * I don't know why people wanted this, but here you go ## Fixed * Chemical plant ports. For real this time. @@ -10,4 +13,6 @@ * Fixed new chemical plant not saving power values to disk * Fixed laser rifle scope texture being missing * Potentially fixed shift clicking issue with the new chemical plant -* Fixed blowtorch having a minimum gas requirement of 1,000mB despite only using 250mB \ No newline at end of file +* Fixed blowtorch having a minimum gas requirement of 1,000mB despite only using 250mB +* The gas turbine now uses audio with a 20 tick timeout, fixing a rare issue where the loop gets stuck and never ends +* Potentially fixed a dupe caused by using InventoryBogoSorter in combination with crates \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/ModBlocks.java b/src/main/java/com/hbm/blocks/ModBlocks.java index 143c33fa0..106dbe846 100644 --- a/src/main/java/com/hbm/blocks/ModBlocks.java +++ b/src/main/java/com/hbm/blocks/ModBlocks.java @@ -1008,6 +1008,7 @@ public class ModBlocks { @Deprecated public static Block machine_chemplant; public static Block machine_chemical_plant; public static Block machine_chemfac; + public static Block machine_chemical_factory; public static Block machine_mixer; public static Block machine_fluidtank; @@ -2227,6 +2228,7 @@ public class ModBlocks { machine_chemplant = new MachineChemplant(Material.iron).setBlockName("machine_chemplant").setHardness(5.0F).setResistance(30.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel"); machine_chemical_plant = new MachineChemicalPlant(Material.iron).setBlockName("machine_chemical_plant").setHardness(5.0F).setResistance(30.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel"); machine_chemfac = new MachineChemfac(Material.iron).setBlockName("machine_chemfac").setHardness(5.0F).setResistance(30.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel"); + machine_chemical_factory = new MachineChemicalFactory(Material.iron).setBlockName("machine_chemical_factory").setHardness(5.0F).setResistance(30.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel"); machine_mixer = new MachineMixer(Material.iron).setBlockName("machine_mixer").setHardness(5.0F).setResistance(30.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel"); machine_fluidtank = new MachineFluidTank(Material.iron).setBlockName("machine_fluidtank").setHardness(5.0F).setResistance(20.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":machine_fluidtank"); machine_bat9000 = new MachineBigAssTank9000(Material.iron).setBlockName("machine_bat9000").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel"); @@ -3267,6 +3269,7 @@ public class ModBlocks { GameRegistry.registerBlock(machine_chemplant, machine_chemplant.getUnlocalizedName()); register(machine_chemical_plant); register(machine_chemfac); + register(machine_chemical_factory); register(machine_arc_welder); register(machine_soldering_station); register(machine_arc_furnace); diff --git a/src/main/java/com/hbm/blocks/generic/BlockReeds.java b/src/main/java/com/hbm/blocks/generic/BlockReeds.java index 77e620c63..5f5cf69fd 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockReeds.java +++ b/src/main/java/com/hbm/blocks/generic/BlockReeds.java @@ -11,6 +11,7 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.init.Blocks; +import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.IIcon; @@ -66,7 +67,7 @@ public class BlockReeds extends Block { @Override public Item getItemDropped(int meta, Random rand, int fortune) { - return null; + return Items.stick; } @Override diff --git a/src/main/java/com/hbm/blocks/machine/MachineChemicalFactory.java b/src/main/java/com/hbm/blocks/machine/MachineChemicalFactory.java new file mode 100644 index 000000000..56ea88967 --- /dev/null +++ b/src/main/java/com/hbm/blocks/machine/MachineChemicalFactory.java @@ -0,0 +1,45 @@ +package com.hbm.blocks.machine; + +import com.hbm.blocks.BlockDummyable; +import com.hbm.tileentity.TileEntityProxyCombo; +import com.hbm.tileentity.machine.TileEntityMachineChemicalFactory; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +public class MachineChemicalFactory extends BlockDummyable { + + public MachineChemicalFactory(Material mat) { + super(mat); + } + + @Override + public TileEntity createNewTileEntity(World world, int meta) { + if(meta >= 12) return new TileEntityMachineChemicalFactory(); + if(meta >= 6) return new TileEntityProxyCombo().inventory().power().fluid(); + return null; + } + + @Override + public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) { + return this.standardOpenBehavior(world, x, y, z, player, 0); + } + + @Override public int[] getDimensions() { return new int[] {2, 0, 2, 2, 2, 2}; } + @Override public int getOffset() { return 2; } + + @Override + public void fillSpace(World world, int x, int y, int z, ForgeDirection dir, int o) { + super.fillSpace(world, x, y, z, dir, o); + + x -= dir.offsetX; + z -= dir.offsetZ; + + for(int i = -2; i <= 2; i++) for(int j = -2; j <= 2; j++) { + if(Math.abs(i) == 2 || Math.abs(j) == 2) this.makeExtra(world, x + i, y, z + j); + } + } +} diff --git a/src/main/java/com/hbm/inventory/container/ContainerBase.java b/src/main/java/com/hbm/inventory/container/ContainerBase.java index 565d8861a..14305fc1c 100644 --- a/src/main/java/com/hbm/inventory/container/ContainerBase.java +++ b/src/main/java/com/hbm/inventory/container/ContainerBase.java @@ -95,7 +95,10 @@ public class ContainerBase extends Container { * @param from the slot index to start from */ public void addSlots(IInventory inv, int from, int x, int y, int rows, int cols) { - int slotSize = 18; + addSlots(inv, from, x, y, rows, cols, 18); + } + + public void addSlots(IInventory inv, int from, int x, int y, int rows, int cols, int slotSize) { for(int row = 0; row < rows; row++) { for(int col = 0; col < cols; col++) { this.addSlotToContainer(new SlotNonRetarded(inv, col + row * cols + from, x + col * slotSize, y + row * slotSize)); @@ -104,14 +107,20 @@ public class ContainerBase extends Container { } public void addOutputSlots(EntityPlayer player, IInventory inv, int from, int x, int y, int rows, int cols) { - int slotSize = 18; + addOutputSlots(player, inv, from, x, y, rows, cols, 18); + } + + public void addOutputSlots(EntityPlayer player, IInventory inv, int from, int x, int y, int rows, int cols, int slotSize) { for(int row = 0; row < rows; row++) for(int col = 0; col < cols; col++) { this.addSlotToContainer(new SlotCraftingOutput(player, inv, col + row * cols + from, x + col * slotSize, y + row * slotSize)); } } public void addTakeOnlySlots(IInventory inv, int from, int x, int y, int rows, int cols) { - int slotSize = 18; + addTakeOnlySlots(inv, from, x, y, rows, cols, 18); + } + + public void addTakeOnlySlots(IInventory inv, int from, int x, int y, int rows, int cols, int slotSize) { for(int row = 0; row < rows; row++) for(int col = 0; col < cols; col++) { this.addSlotToContainer(new SlotTakeOnly(inv, col + row * cols + from, x + col * slotSize, y + row * slotSize)); } diff --git a/src/main/java/com/hbm/inventory/container/ContainerCrateBase.java b/src/main/java/com/hbm/inventory/container/ContainerCrateBase.java index ec6309430..06b255a68 100644 --- a/src/main/java/com/hbm/inventory/container/ContainerCrateBase.java +++ b/src/main/java/com/hbm/inventory/container/ContainerCrateBase.java @@ -24,7 +24,7 @@ public class ContainerCrateBase extends ContainerBase { } for(int i = 0; i < 9; i++) { - this.addSlotToContainer(new SlotNonRetarded(invPlayer, i, playerInvX + i * 18, playerHotbarY)); + this.addSlotToContainer(new SlotPlayerCrate(invPlayer, i, playerInvX + i * 18, playerHotbarY)); } } @@ -67,5 +67,11 @@ public class ContainerCrateBase extends ContainerBase { return false; return super.canTakeStack(player); } + + @Override + public boolean isItemValid(ItemStack item) { + if(ItemStack.areItemStacksEqual(getStack(), item)) return false; + return super.isItemValid(item); + } } } diff --git a/src/main/java/com/hbm/inventory/container/ContainerMachineChemicalFactory.java b/src/main/java/com/hbm/inventory/container/ContainerMachineChemicalFactory.java new file mode 100644 index 000000000..484dcfc21 --- /dev/null +++ b/src/main/java/com/hbm/inventory/container/ContainerMachineChemicalFactory.java @@ -0,0 +1,77 @@ +package com.hbm.inventory.container; + +import com.hbm.inventory.SlotCraftingOutput; +import com.hbm.inventory.SlotNonRetarded; +import com.hbm.items.ModItems; +import com.hbm.items.machine.ItemMachineUpgrade; +import com.hbm.util.InventoryUtil; + +import api.hbm.energymk2.IBatteryItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +public class ContainerMachineChemicalFactory extends ContainerBase { + + public ContainerMachineChemicalFactory(InventoryPlayer invPlayer, IInventory chemicalPlant) { + super(invPlayer, chemicalPlant); + + // Battery + this.addSlotToContainer(new SlotNonRetarded(chemicalPlant, 0, 224, 88)); + // Upgrades + this.addSlots(chemicalPlant, 1, 206, 125, 3, 1); + + for(int i = 0; i < 4; i++) { + // Template + this.addSlots(chemicalPlant, 4 + i * 7, 93, 20 + i * 22, 1, 1, 16); + // Solid Input + this.addSlots(chemicalPlant, 5 + i * 7, 10, 20 + i * 22, 1, 3, 16); + // Solid Output + this.addOutputSlots(invPlayer.player, chemicalPlant, 8 + i * 7, 139, 20 + i * 22, 1, 3, 16); + } + + this.playerInv(invPlayer, 26, 134); + } + + @Override + public ItemStack transferStackInSlot(EntityPlayer player, int index) { + ItemStack slotOriginal = null; + Slot slot = (Slot) this.inventorySlots.get(index); + + if(slot != null && slot.getHasStack()) { + ItemStack slotStack = slot.getStack(); + slotOriginal = slotStack.copy(); + + if(index <= tile.getSizeInventory() - 1) { + SlotCraftingOutput.checkAchievements(player, slotStack); + if(!this.mergeItemStack(slotStack, tile.getSizeInventory(), this.inventorySlots.size(), true)) { + return null; + } + } else { + + if(slotOriginal.getItem() instanceof IBatteryItem || slotOriginal.getItem() == ModItems.battery_creative) { + if(!this.mergeItemStack(slotStack, 0, 1, false)) return null; + } else if(slotOriginal.getItem() instanceof ItemMachineUpgrade) { + if(!this.mergeItemStack(slotStack, 1, 4, false)) return null; + } else { + if(!InventoryUtil.mergeItemStack(this.inventorySlots, slotStack, 5, 8, false) && + !InventoryUtil.mergeItemStack(this.inventorySlots, slotStack, 12, 15, false) && + !InventoryUtil.mergeItemStack(this.inventorySlots, slotStack, 19, 22, false) && + !InventoryUtil.mergeItemStack(this.inventorySlots, slotStack, 26, 29, false)) return null; + } + } + + if(slotStack.stackSize == 0) { + slot.putStack(null); + } else { + slot.onSlotChanged(); + } + + slot.onPickupFromSlot(player, slotStack); + } + + return slotOriginal; + } +} diff --git a/src/main/java/com/hbm/inventory/fluid/tank/FluidTank.java b/src/main/java/com/hbm/inventory/fluid/tank/FluidTank.java index 4883790dc..9d60e8a2a 100644 --- a/src/main/java/com/hbm/inventory/fluid/tank/FluidTank.java +++ b/src/main/java/com/hbm/inventory/fluid/tank/FluidTank.java @@ -65,6 +65,12 @@ public class FluidTank implements Cloneable { this.setFill(0); } + public void resetTank() { + this.type = Fluids.NONE; + this.fluid = 0; + this.pressure = 0; + } + /** Changes type and pressure based on a fluid stack, useful for changing tank types based on recipes */ public FluidTank conform(FluidStack stack) { this.setTankType(stack.type); diff --git a/src/main/java/com/hbm/inventory/gui/GUIMachineChemicalFactory.java b/src/main/java/com/hbm/inventory/gui/GUIMachineChemicalFactory.java new file mode 100644 index 000000000..07824714e --- /dev/null +++ b/src/main/java/com/hbm/inventory/gui/GUIMachineChemicalFactory.java @@ -0,0 +1,132 @@ +package com.hbm.inventory.gui; + +import org.lwjgl.opengl.GL11; + +import com.hbm.inventory.container.ContainerMachineChemicalFactory; +import com.hbm.inventory.recipes.ChemicalPlantRecipes; +import com.hbm.inventory.recipes.loader.GenericRecipe; +import com.hbm.lib.RefStrings; +import com.hbm.tileentity.machine.TileEntityMachineChemicalFactory; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Slot; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; + +public class GUIMachineChemicalFactory extends GuiInfoContainer { + + private static ResourceLocation texture = new ResourceLocation(RefStrings.MODID + ":textures/gui/processing/gui_chemical_factory.png"); + private TileEntityMachineChemicalFactory chemplant; + + public GUIMachineChemicalFactory(InventoryPlayer invPlayer, TileEntityMachineChemicalFactory tedf) { + super(new ContainerMachineChemicalFactory(invPlayer, tedf)); + chemplant = tedf; + + this.xSize = 248; + this.ySize = 216; + } + + @Override + public void drawScreen(int mouseX, int mouseY, float f) { + super.drawScreen(mouseX, mouseY, f); + + for(int i = 0; i < 3; i++) for(int j = 0; j < 4; j++) { + chemplant.inputTanks[i].renderTankInfo(this, mouseX, mouseY, guiLeft + 60 + i * 5, guiTop + 20 + j * 22, 4, 16); + chemplant.outputTanks[i].renderTankInfo(this, mouseX, mouseY, guiLeft + 189 + i * 5, guiTop + 20 + j * 22, 4, 16); + } + + this.drawElectricityInfo(this, mouseX, mouseY, guiLeft + 224, guiTop + 18, 16, 68, chemplant.power, chemplant.maxPower); + + for(int i = 0; i < 4; i++) if(guiLeft + 74 <= mouseX && guiLeft + 74 + 18 > mouseX && guiTop + 19 + i * 22 < mouseY && guiTop + 19 + i * 22 + 18 >= mouseY) { + if(this.chemplant.chemplantModule[i].recipe != null && ChemicalPlantRecipes.INSTANCE.recipeNameMap.containsKey(this.chemplant.chemplantModule[i].recipe)) { + GenericRecipe recipe = (GenericRecipe) ChemicalPlantRecipes.INSTANCE.recipeNameMap.get(this.chemplant.chemplantModule[i].recipe); + this.func_146283_a(recipe.print(), mouseX, mouseY); + } else { + this.drawCreativeTabHoveringText(EnumChatFormatting.YELLOW + "Click to set recipe", mouseX, mouseY); + } + } + } + + @Override + protected void mouseClicked(int x, int y, int button) { + super.mouseClicked(x, y, button); + + for(int i = 0; i < 4; i++) if(this.checkClick(x, y, 74, 19 + i * 22, 18, 18)) GUIScreenRecipeSelector.openSelector(ChemicalPlantRecipes.INSTANCE, chemplant, chemplant.chemplantModule[i].recipe, i, this); + } + + @Override + protected void drawGuiContainerForegroundLayer(int i, int j) { + String name = this.chemplant.hasCustomInventoryName() ? this.chemplant.getInventoryName() : I18n.format(this.chemplant.getInventoryName()); + + this.fontRendererObj.drawString(name, 106 - this.fontRendererObj.getStringWidth(name) / 2, 6, 4210752); + this.fontRendererObj.drawString(I18n.format("container.inventory"), 26, this.ySize - 96 + 2, 4210752); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float p_146976_1_, int p_146976_2_, int p_146976_3_) { + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + Minecraft.getMinecraft().getTextureManager().bindTexture(texture); + drawTexturedModalRect(guiLeft, guiTop, 0, 0, 248, 116); + drawTexturedModalRect(guiLeft + 18, guiTop + 116, 18, 116, 230, 100); + + int p = (int) (chemplant.power * 68 / chemplant.maxPower); + drawTexturedModalRect(guiLeft + 224, guiTop + 86 - p, 0, 184 - p, 16, p); + + for(int i = 0; i < 4; i++) if(chemplant.chemplantModule[i].progress > 0) { + int j = (int) Math.ceil(22 * chemplant.chemplantModule[i].progress); + drawTexturedModalRect(guiLeft + 113, guiTop + 29 + i * 22, 0, 216, j, 6); + } + + for(int g = 0; g < 4; g++) { + GenericRecipe recipe = ChemicalPlantRecipes.INSTANCE.recipeNameMap.get(chemplant.chemplantModule[g].recipe); + + /// LEFT LED + if(chemplant.didProcess) { + drawTexturedModalRect(guiLeft + 113, guiTop + 21 + g * 22, 4, 222, 4, 4); + } else if(recipe != null) { + drawTexturedModalRect(guiLeft + 113, guiTop + 21 + g * 22, 0, 222, 4, 4); + } + + /// RIGHT LED + if(chemplant.didProcess) { + drawTexturedModalRect(guiLeft + 121, guiTop + 21 + g * 22, 4, 222, 4, 4); + } else if(recipe != null && chemplant.power >= recipe.power) { + drawTexturedModalRect(guiLeft + 121, guiTop + 21 + g * 22, 0, 222, 4, 4); + } + } + + for(int g = 0; g < 4; g++) { // not a great way of doing it but at least we eliminate state leak bullshit + GenericRecipe recipe = ChemicalPlantRecipes.INSTANCE.recipeNameMap.get(chemplant.chemplantModule[g].recipe); + + this.renderItem(recipe != null ? recipe.getIcon() : TEMPLATE_FOLDER, 75, 20 + g * 22); + + if(recipe != null && recipe.inputItem != null) { + for(int i = 0; i < recipe.inputItem.length; i++) { + Slot slot = (Slot) this.inventorySlots.inventorySlots.get(chemplant.chemplantModule[g].inputSlots[i]); + if(!slot.getHasStack()) this.renderItem(recipe.inputItem[i].extractForCyclingDisplay(20), slot.xDisplayPosition, slot.yDisplayPosition, 10F); + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(texture); + OpenGlHelper.glBlendFunc(770, 771, 1, 0); + GL11.glColor4f(1F, 1F, 1F, 0.5F); + GL11.glEnable(GL11.GL_BLEND); + this.zLevel = 300F; + for(int i = 0; i < recipe.inputItem.length; i++) { + Slot slot = (Slot) this.inventorySlots.inventorySlots.get(chemplant.chemplantModule[g].inputSlots[i]); + if(!slot.getHasStack()) drawTexturedModalRect(guiLeft + slot.xDisplayPosition, guiTop + slot.yDisplayPosition, slot.xDisplayPosition, slot.yDisplayPosition, 16, 16); + } + this.zLevel = 0F; + GL11.glColor4f(1F, 1F, 1F, 1F); + GL11.glDisable(GL11.GL_BLEND); + } + } + + for(int i = 0; i < 3; i++) for(int j = 0; j < 4; j++) { + chemplant.inputTanks[i + j * 3].renderTank(guiLeft + 60 + i * 5, guiTop + 36 + j * 22, this.zLevel, 4, 16); + chemplant.outputTanks[i + j * 3].renderTank(guiLeft + 189 + i * 5, guiTop + 36 + j * 22, this.zLevel, 4, 16); + } + } +} diff --git a/src/main/java/com/hbm/main/ClientProxy.java b/src/main/java/com/hbm/main/ClientProxy.java index 5c157900b..128a8f8b4 100644 --- a/src/main/java/com/hbm/main/ClientProxy.java +++ b/src/main/java/com/hbm/main/ClientProxy.java @@ -91,6 +91,7 @@ import com.hbm.util.fauxpointtwelve.BlockPos; import com.hbm.util.i18n.I18nClient; import com.hbm.util.i18n.ITranslate; import com.hbm.wiaj.cannery.Jars; + import cpw.mods.fml.client.registry.ClientRegistry; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.common.FMLCommonHandler; @@ -270,6 +271,7 @@ public class ClientProxy extends ServerProxy { ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineChemplant.class, new RenderChemplant()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineChemicalPlant.class, new RenderChemicalPlant()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineChemfac.class, new RenderChemfac()); + ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineChemicalFactory.class, new RenderChemicalFactory()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineFluidTank.class, new RenderFluidTank()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineBAT9000.class, new RenderBAT9000()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineOrbus.class, new RenderOrbus()); diff --git a/src/main/java/com/hbm/main/ResourceManager.java b/src/main/java/com/hbm/main/ResourceManager.java index 2547277ca..8cad667ec 100644 --- a/src/main/java/com/hbm/main/ResourceManager.java +++ b/src/main/java/com/hbm/main/ResourceManager.java @@ -150,6 +150,7 @@ public class ResourceManager { public static final IModelCustom chemplant_fluidcap = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/chemplant_new_fluidcap.hmf")); public static final IModelCustom chemical_plant = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/chemical_plant.obj")); public static final IModelCustom chemfac = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/chemfac.obj")); + public static final IModelCustom chemical_factory = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/chemical_factory.obj")); //Mixer public static final IModelCustom mixer = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/mixer.obj")); @@ -583,6 +584,7 @@ public class ResourceManager { public static final ResourceLocation chemical_plant_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/chemical_plant.png"); public static final ResourceLocation chemical_plant_fluid_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/chemical_plant_fluid.png"); public static final ResourceLocation chemfac_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/chemfac.png"); + public static final ResourceLocation chemical_factory_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/chemical_factory.png"); //Mixer public static final ResourceLocation mixer_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/mixer.png"); diff --git a/src/main/java/com/hbm/module/ModuleMachineChemplant.java b/src/main/java/com/hbm/module/ModuleMachineChemplant.java index 06fe32d84..c68e9cae6 100644 --- a/src/main/java/com/hbm/module/ModuleMachineChemplant.java +++ b/src/main/java/com/hbm/module/ModuleMachineChemplant.java @@ -43,8 +43,8 @@ public class ModuleMachineChemplant { /** Chances tank type and pressure based on recipe */ public void setupTanks(GenericRecipe recipe) { if(recipe == null) return; - if(recipe.inputFluid != null) for(int i = 0; i < Math.min(inputTanks.length, recipe.inputFluid.length); i++) inputTanks[i].conform(recipe.inputFluid[i]); - if(recipe.outputFluid != null) for(int i = 0; i < Math.min(outputTanks.length, recipe.outputFluid.length); i++) outputTanks[i].conform(recipe.outputFluid[i]); + for(int i = 0; i < 3; i++) if(recipe.inputFluid != null && recipe.inputFluid.length > i) inputTanks[i].conform(recipe.inputFluid[i]); else inputTanks[i].resetTank(); + for(int i = 0; i < 3; i++) if(recipe.outputFluid != null && recipe.outputFluid.length > i) outputTanks[i].conform(recipe.outputFluid[i]); else outputTanks[i].resetTank(); } /** Expects the tanks to be set up correctly beforehand */ diff --git a/src/main/java/com/hbm/render/tileentity/RenderChemicalFactory.java b/src/main/java/com/hbm/render/tileentity/RenderChemicalFactory.java new file mode 100644 index 000000000..7eae5b7ad --- /dev/null +++ b/src/main/java/com/hbm/render/tileentity/RenderChemicalFactory.java @@ -0,0 +1,71 @@ +package com.hbm.render.tileentity; + +import org.lwjgl.opengl.GL11; + +import com.hbm.blocks.BlockDummyable; +import com.hbm.blocks.ModBlocks; +import com.hbm.main.ResourceManager; +import com.hbm.render.item.ItemRenderBase; +import com.hbm.tileentity.machine.TileEntityMachineChemicalFactory; + +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.client.IItemRenderer; + +public class RenderChemicalFactory extends TileEntitySpecialRenderer implements IItemRendererProvider { + + @Override + public void renderTileEntityAt(TileEntity tileEntity, double x, double y, double z, float interp) { + GL11.glPushMatrix(); + GL11.glTranslated(x + 0.5, y, z + 0.5); + GL11.glRotated(90, 0, 1, 0); + GL11.glShadeModel(GL11.GL_SMOOTH); + + switch(tileEntity.getBlockMetadata() - BlockDummyable.offset) { + case 2: GL11.glRotatef(0, 0F, 1F, 0F); break; + case 4: GL11.glRotatef(90, 0F, 1F, 0F); break; + case 3: GL11.glRotatef(180, 0F, 1F, 0F); break; + case 5: GL11.glRotatef(270, 0F, 1F, 0F); break; + } + + TileEntityMachineChemicalFactory chemplant = (TileEntityMachineChemicalFactory) tileEntity; + float anim = chemplant.prevAnim + (chemplant.anim - chemplant.prevAnim) * interp; + + bindTexture(ResourceManager.chemical_factory_tex); + ResourceManager.chemical_factory.renderPart("Base"); + if(chemplant.frame) ResourceManager.chemical_factory.renderPart("Frame"); + ResourceManager.chemical_factory.renderPart("Fan1"); + ResourceManager.chemical_factory.renderPart("Fan2"); + + GL11.glShadeModel(GL11.GL_FLAT); + GL11.glPopMatrix(); + } + + @Override + public Item getItemForRenderer() { + return Item.getItemFromBlock(ModBlocks.machine_chemical_factory); + } + + @Override + public IItemRenderer getRenderer() { + + return new ItemRenderBase() { + + public void renderInventory() { + GL11.glTranslated(0, -1.5, 0); + GL11.glScaled(3, 3, 3); + } + public void renderCommonWithStack(ItemStack item) { + GL11.glScaled(0.75, 0.75, 0.75); + GL11.glShadeModel(GL11.GL_SMOOTH); + bindTexture(ResourceManager.chemical_factory_tex); + ResourceManager.chemical_factory.renderPart("Base"); + ResourceManager.chemical_factory.renderPart("Frame"); + ResourceManager.chemical_factory.renderPart("Fan1"); + ResourceManager.chemical_factory.renderPart("Fan2"); + GL11.glShadeModel(GL11.GL_FLAT); + }}; + } +} diff --git a/src/main/java/com/hbm/tileentity/TileMappings.java b/src/main/java/com/hbm/tileentity/TileMappings.java index f8252b5af..36e0f3d04 100644 --- a/src/main/java/com/hbm/tileentity/TileMappings.java +++ b/src/main/java/com/hbm/tileentity/TileMappings.java @@ -342,6 +342,7 @@ public class TileMappings { put(TileEntityMachineChemplant.class, "tileentity_chemical_plant"); put(TileEntityMachineChemicalPlant.class, "tileentity_chemicalplant"); put(TileEntityMachineChemfac.class, "tileentity_chemfac"); + put(TileEntityMachineChemicalFactory.class, "tileentity_chemicalfactory"); put(TileEntityMachineOilWell.class, "tileentity_derrick"); put(TileEntityMachinePumpjack.class, "tileentity_machine_pumpjack"); diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalFactory.java b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalFactory.java new file mode 100644 index 000000000..1487d194a --- /dev/null +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalFactory.java @@ -0,0 +1,293 @@ +package com.hbm.tileentity.machine; + +import java.util.HashMap; +import java.util.List; + +import com.hbm.blocks.ModBlocks; +import com.hbm.interfaces.IControlReceiver; +import com.hbm.inventory.UpgradeManagerNT; +import com.hbm.inventory.container.ContainerMachineChemicalFactory; +import com.hbm.inventory.fluid.Fluids; +import com.hbm.inventory.fluid.tank.FluidTank; +import com.hbm.inventory.gui.GUIMachineChemicalFactory; +import com.hbm.items.machine.ItemMachineUpgrade; +import com.hbm.items.machine.ItemMachineUpgrade.UpgradeType; +import com.hbm.lib.Library; +import com.hbm.module.ModuleMachineChemplant; +import com.hbm.tileentity.IGUIProvider; +import com.hbm.tileentity.IUpgradeInfoProvider; +import com.hbm.tileentity.TileEntityMachineBase; +import com.hbm.util.BobMathUtil; +import com.hbm.util.fauxpointtwelve.DirPos; +import com.hbm.util.i18n.I18nUtil; + +import api.hbm.energymk2.IEnergyReceiverMK2; +import api.hbm.fluidmk2.IFluidStandardTransceiverMK2; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +public class TileEntityMachineChemicalFactory extends TileEntityMachineBase implements IEnergyReceiverMK2, IFluidStandardTransceiverMK2, IUpgradeInfoProvider, IControlReceiver, IGUIProvider { + + public FluidTank[] allTanks; + public FluidTank[] inputTanks; + public FluidTank[] outputTanks; + + public long power; + public long maxPower = 10_000_000; + public boolean didProcess = false; + + public boolean frame = false; + public int anim; + public int prevAnim; + + public ModuleMachineChemplant[] chemplantModule; + public UpgradeManagerNT upgradeManager = new UpgradeManagerNT(this); + + public TileEntityMachineChemicalFactory() { + super(32); + + this.inputTanks = new FluidTank[12]; + this.outputTanks = new FluidTank[12]; + for(int i = 0; i < 12; i++) { + this.inputTanks[i] = new FluidTank(Fluids.NONE, 24_000); + this.outputTanks[i] = new FluidTank(Fluids.NONE, 24_000); + } + + this.allTanks = new FluidTank[this.inputTanks.length + this.outputTanks.length]; + for(int i = 0; i < inputTanks.length; i++) this.allTanks[i] = this.inputTanks[i]; + for(int i = 0; i < outputTanks.length; i++) this.allTanks[i + this.inputTanks.length] = this.outputTanks[i]; + + this.chemplantModule = new ModuleMachineChemplant[4]; + for(int i = 0; i < 4; i++) this.chemplantModule[i] = new ModuleMachineChemplant(i, this, slots) + .itemInput(5 + i * 7, 6 + i * 7, 7 + i * 7) + .itemOutput(8 + i * 7, 9 + i * 7, 10 + i * 7) + .fluidInput(inputTanks[0 + i * 3], inputTanks[1 + i * 3], inputTanks[2 + i * 3]) + .fluidOutput(outputTanks[0 + i * 3], outputTanks[1 + i * 3], outputTanks[2 + i * 3]); + } + + @Override + public boolean canExtractItem(int i, ItemStack itemStack, int j) { + if(i >= 8 && i <= 10) return true; + if(i >= 12 && i <= 14) return true; + if(i >= 19 && i <= 21) return true; + if(i >= 26 && i <= 28) return true; + return false; + } + + @Override + public boolean isItemValidForSlot(int slot, ItemStack stack) { + if(slot == 0) return true; // battery + if(slot >= 1 && slot <= 3 && stack.getItem() instanceof ItemMachineUpgrade) return true; // upgrades + for(int i = 0; i < 4; i++) if(this.chemplantModule[i].isItemValid(slot, stack)) return true; // recipe input crap + return false; + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) { + return new int[] { + 5, 6, 7, 8, 9, 10, + 12, 13, 14, 15, 16, 17, + 19, 20, 21, 22, 23, 24, + 26, 27, 28, 29, 30, 31 + }; + } + + @Override + public String getName() { + return "container.machineChemicalFactory"; + } + + @Override + public void updateEntity() { + + if(maxPower <= 0) this.maxPower = 10_000_000; + + if(!worldObj.isRemote) { + + this.power = Library.chargeTEFromItems(slots, 0, power, maxPower); + upgradeManager.checkSlots(slots, 1, 3); + + inputTanks[0].loadTank(10, 13, slots); + inputTanks[1].loadTank(11, 14, slots); + inputTanks[2].loadTank(12, 15, slots); + + outputTanks[0].unloadTank(16, 19, slots); + outputTanks[1].unloadTank(17, 20, slots); + outputTanks[2].unloadTank(18, 21, slots); + + for(DirPos pos : getConPos()) { + this.trySubscribe(worldObj, pos); + for(FluidTank tank : inputTanks) if(tank.getTankType() != Fluids.NONE) this.trySubscribe(tank.getTankType(), worldObj, pos); + for(FluidTank tank : outputTanks) if(tank.getFill() > 0) this.tryProvide(tank, worldObj, pos); + } + + double speed = 1D; + double pow = 1D; + + speed += Math.min(upgradeManager.getLevel(UpgradeType.SPEED), 3) / 3D; + speed += Math.min(upgradeManager.getLevel(UpgradeType.OVERDRIVE), 3); + + pow -= Math.min(upgradeManager.getLevel(UpgradeType.POWER), 3) * 0.25D; + pow += Math.min(upgradeManager.getLevel(UpgradeType.SPEED), 3) * 1D; + pow += Math.min(upgradeManager.getLevel(UpgradeType.OVERDRIVE), 3) * 10D / 3D; + + this.didProcess = false; + boolean markDirty = false; + + for(int i = 0; i < 4; i++) { + this.chemplantModule[i].update(speed * 2D, pow); + this.didProcess |= this.chemplantModule[i].didProcess; + markDirty |= this.chemplantModule[i].markDirty; + } + + if(markDirty) this.markDirty(); + + this.networkPackNT(100); + + } else { + + this.prevAnim = this.anim; + if(this.didProcess) this.anim++; + + if(worldObj.getTotalWorldTime() % 20 == 0) { + frame = !worldObj.getBlock(xCoord, yCoord + 3, zCoord).isAir(worldObj, xCoord, yCoord + 3, zCoord); + } + } + } + + public DirPos[] getConPos() { + ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - 10); + ForgeDirection rot = dir.getRotation(ForgeDirection.UP); + return new DirPos[] { + new DirPos(xCoord + 3, yCoord, zCoord - 2, Library.POS_X), + new DirPos(xCoord + 3, yCoord, zCoord + 0, Library.POS_X), + new DirPos(xCoord + 3, yCoord, zCoord + 2, Library.POS_X), + new DirPos(xCoord - 3, yCoord, zCoord - 2, Library.NEG_X), + new DirPos(xCoord - 3, yCoord, zCoord + 0, Library.NEG_X), + new DirPos(xCoord - 3, yCoord, zCoord + 2, Library.NEG_X), + new DirPos(xCoord - 2, yCoord, zCoord + 3, Library.POS_Z), + new DirPos(xCoord + 0, yCoord, zCoord + 3, Library.POS_Z), + new DirPos(xCoord + 2, yCoord, zCoord + 3, Library.POS_Z), + new DirPos(xCoord - 2, yCoord, zCoord - 3, Library.NEG_Z), + new DirPos(xCoord + 0, yCoord, zCoord - 3, Library.NEG_Z), + new DirPos(xCoord + 2, yCoord, zCoord - 3, Library.NEG_Z), + + new DirPos(xCoord + dir.offsetX + rot.offsetX * 3, yCoord, zCoord + dir.offsetZ + rot.offsetZ * 3, rot), + new DirPos(xCoord - dir.offsetX + rot.offsetX * 3, yCoord, zCoord - dir.offsetZ + rot.offsetZ * 3, rot), + new DirPos(xCoord + dir.offsetX - rot.offsetX * 3, yCoord, zCoord + dir.offsetZ - rot.offsetZ * 3, rot.getOpposite()), + new DirPos(xCoord - dir.offsetX - rot.offsetX * 3, yCoord, zCoord - dir.offsetZ - rot.offsetZ * 3, rot.getOpposite()), + }; + } + + + public DirPos[] getCoolPos() { + ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - 10); + ForgeDirection rot = dir.getRotation(ForgeDirection.UP); + + return new DirPos[] { + new DirPos(xCoord + rot.offsetX + dir.offsetX * 3, yCoord, zCoord + rot.offsetZ + dir.offsetZ * 3, dir), + new DirPos(xCoord - rot.offsetX + dir.offsetX * 3, yCoord, zCoord - rot.offsetZ + dir.offsetZ * 3, dir), + new DirPos(xCoord + rot.offsetX - dir.offsetX * 3, yCoord, zCoord + rot.offsetZ - dir.offsetZ * 3, dir.getOpposite()), + new DirPos(xCoord - rot.offsetX - dir.offsetX * 3, yCoord, zCoord - rot.offsetZ - dir.offsetZ * 3, dir.getOpposite()), + }; + } + + @Override + public void serialize(ByteBuf buf) { + super.serialize(buf); + for(FluidTank tank : inputTanks) tank.serialize(buf); + for(FluidTank tank : outputTanks) tank.serialize(buf); + buf.writeLong(power); + buf.writeLong(maxPower); + buf.writeBoolean(didProcess); + for(int i = 0; i < 4; i++) this.chemplantModule[i].serialize(buf); + } + + @Override + public void deserialize(ByteBuf buf) { + super.deserialize(buf); + for(FluidTank tank : inputTanks) tank.deserialize(buf); + for(FluidTank tank : outputTanks) tank.deserialize(buf); + this.power = buf.readLong(); + this.maxPower = buf.readLong(); + this.didProcess = buf.readBoolean(); + for(int i = 0; i < 4; i++) this.chemplantModule[i].deserialize(buf); + } + + @Override public long getPower() { return power; } + @Override public void setPower(long power) { this.power = power; } + @Override public long getMaxPower() { return maxPower; } + + @Override public FluidTank[] getReceivingTanks() { return inputTanks; } + @Override public FluidTank[] getSendingTanks() { return outputTanks; } + @Override public FluidTank[] getAllTanks() { return allTanks; } + + @Override public Container provideContainer(int ID, EntityPlayer player, World world, int x, int y, int z) { return new ContainerMachineChemicalFactory(player.inventory, this); } + @Override @SideOnly(Side.CLIENT) public Object provideGUI(int ID, EntityPlayer player, World world, int x, int y, int z) { return new GUIMachineChemicalFactory(player.inventory, this); } + + @Override public boolean hasPermission(EntityPlayer player) { return this.isUseableByPlayer(player); } + + @Override + public void receiveControl(NBTTagCompound data) { + if(data.hasKey("index") && data.hasKey("selection")) { + int index = data.getInteger("index"); + String selection = data.getString("selection"); + if(index >= 0 && index < 4) { + this.chemplantModule[index].recipe = selection; + this.markChanged(); + } + } + } + + AxisAlignedBB bb = null; + + @Override + public AxisAlignedBB getRenderBoundingBox() { + if(bb == null) bb = AxisAlignedBB.getBoundingBox(xCoord - 2, yCoord, zCoord - 2, xCoord + 3, yCoord + 3, zCoord + 3); + return bb; + } + + @Override + @SideOnly(Side.CLIENT) + public double getMaxRenderDistanceSquared() { + return 65536.0D; + } + + @Override + public boolean canProvideInfo(UpgradeType type, int level, boolean extendedInfo) { + return type == UpgradeType.SPEED || type == UpgradeType.POWER || type == UpgradeType.OVERDRIVE; + } + + @Override + public void provideInfo(UpgradeType type, int level, List info, boolean extendedInfo) { + info.add(IUpgradeInfoProvider.getStandardLabel(ModBlocks.machine_chemical_plant)); + if(type == UpgradeType.SPEED) { + info.add(EnumChatFormatting.GREEN + I18nUtil.resolveKey(KEY_SPEED, "+" + (level * 100 / 3) + "%")); + info.add(EnumChatFormatting.RED + I18nUtil.resolveKey(KEY_CONSUMPTION, "+" + (level * 50) + "%")); + } + if(type == UpgradeType.POWER) { + info.add(EnumChatFormatting.GREEN + I18nUtil.resolveKey(KEY_CONSUMPTION, "-" + (level * 25) + "%")); + } + if(type == UpgradeType.OVERDRIVE) { + info.add((BobMathUtil.getBlink() ? EnumChatFormatting.RED : EnumChatFormatting.DARK_GRAY) + "YES"); + } + } + + @Override + public HashMap getValidUpgrades() { + HashMap upgrades = new HashMap<>(); + upgrades.put(UpgradeType.SPEED, 3); + upgrades.put(UpgradeType.POWER, 3); + upgrades.put(UpgradeType.OVERDRIVE, 3); + return upgrades; + } +} diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalPlant.java b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalPlant.java index 0dc1dd1ad..8181d3497 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalPlant.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalPlant.java @@ -228,8 +228,10 @@ public class TileEntityMachineChemicalPlant extends TileEntityMachineBase implem if(data.hasKey("index") && data.hasKey("selection")) { int index = data.getInteger("index"); String selection = data.getString("selection"); - if(index == 0) this.chemplantModule.recipe = selection; - this.markChanged(); + if(index == 0) { + this.chemplantModule.recipe = selection; + this.markChanged(); + } } } diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineTurbineGas.java b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineTurbineGas.java index 2e320fb2e..26a44455f 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineTurbineGas.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineTurbineGas.java @@ -74,7 +74,7 @@ public class TileEntityMachineTurbineGas extends TileEntityMachineBase implement fuelMaxCons.put(Fluids.GAS, 50D); // natgas doesn't burn well so it burns faster to compensate fuelMaxCons.put(Fluids.SYNGAS, 10D); // syngas just fucks fuelMaxCons.put(Fluids.OXYHYDROGEN, 100D); // oxyhydrogen is terrible so it needs to burn a ton for the bare minimum - fuelMaxCons.put(Fluids.REFORMGAS, 5D); // fuck it we ball + fuelMaxCons.put(Fluids.REFORMGAS, 5D); // fuck it we ball // default to 5 if not in list } @@ -166,17 +166,18 @@ public class TileEntityMachineTurbineGas extends TileEntityMachineBase implement if(audio == null) { //if there is no sound playing, start it - audio = MainRegistry.proxy.getLoopedSound("hbm:block.turbinegasRunning", xCoord, yCoord, zCoord, getVolume(1.0F), 20F, 2.0F); + audio = MainRegistry.proxy.getLoopedSound("hbm:block.turbinegasRunning", xCoord, yCoord, zCoord, getVolume(1.0F), 20F, 2.0F, 20); audio.startSound(); } else if(!audio.isPlaying()) { audio.stopSound(); - audio = MainRegistry.proxy.getLoopedSound("hbm:block.turbinegasRunning", xCoord, yCoord, zCoord, getVolume(1.0F), 20F, 2.0F); + audio = MainRegistry.proxy.getLoopedSound("hbm:block.turbinegasRunning", xCoord, yCoord, zCoord, getVolume(1.0F), 20F, 2.0F, 20); audio.startSound(); } audio.updatePitch((float) (0.55 + 0.1 * rpm / 10)); //dynamic pitch update based on rpm audio.updateVolume(getVolume(2F)); //yeah i need this + audio.keepAlive(); } else { diff --git a/src/main/resources/assets/hbm/textures/gui/processing/gui_chemical_factory.png b/src/main/resources/assets/hbm/textures/gui/processing/gui_chemical_factory.png index d8ce9926c1d1a6d67a6aed1a7959cce567b90002..7e6aa8347e4fff3bda07f1e73bea1f64835e6b4c 100644 GIT binary patch literal 3531 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 literal 3840 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 diff --git a/src/main/resources/assets/hbm/textures/items/billet_yharonite.png b/src/main/resources/assets/hbm/textures/items/billet_yharonite.png index 27f0cfb0f0e305f8ae778b93a0d7bf3252ee74d9..8778d6f03e04edfd2768a805aba7d9190f671660 100644 GIT binary patch delta 270 zcmV+p0rCFe0=NQ@Gk*Z@Nkl_x1k+GAnuF#MWJY3LV*LKa>)Qx`16vCYrXc~aSjObXTr<`s zzI2DzasP?XyJ(SQv5WyojydboPSpxT0x*AmWOIH1pePEGs?~&R1+GZqg8wK#5Eoa7 UnZ96j00000Ne4wvM6N<$f}RO}H2?qr delta 310 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 WiWeil_3DcN0000