From 1ad65345b08cc40864d9fa566ce014e2606217d7 Mon Sep 17 00:00:00 2001 From: Boblet Date: Wed, 11 Feb 2026 14:11:21 +0100 Subject: [PATCH] bringeth forth the sriracha nuggets --- src/main/java/com/hbm/blocks/ModBlocks.java | 23 +- .../blocks/machine/FurnaceCombination.java | 3 +- .../hbm/blocks/machine/MachineChungus.java | 41 +-- .../machine/MachineIndustrialTurbine.java | 120 ++++++++ .../blocks/machine/MachineLargeTurbine.java | 1 + .../java/com/hbm/entity/mob/EntityFBI.java | 7 +- .../recipes/AssemblyMachineRecipes.java | 4 +- src/main/java/com/hbm/main/ClientProxy.java | 1 + .../java/com/hbm/main/ResourceManager.java | 16 +- .../hbm/render/loader/HFRWavefrontObject.java | 11 + .../tileentity/RenderIndustrialTurbine.java | 92 ++++++ .../hbm/tileentity/TileEntityProxyCombo.java | 7 +- .../java/com/hbm/tileentity/TileMappings.java | 1 + .../tileentity/machine/TileEntityChungus.java | 279 +++++------------- .../TileEntityMachineIndustrialTurbine.java | 163 ++++++++++ .../TileEntityMachineLargeTurbine.java | 28 +- .../machine/TileEntitySteamEngine.java | 2 +- .../machine/TileEntityTurbineBase.java | 185 ++++++++++++ .../models/machines/industrial_turbine.obj | 2 +- .../hbm/textures/models/machines/chungus.png | Bin 16198 -> 16204 bytes .../models/machines/industrial_turbine.png | Bin 2825 -> 10230 bytes 21 files changed, 691 insertions(+), 295 deletions(-) create mode 100644 src/main/java/com/hbm/blocks/machine/MachineIndustrialTurbine.java create mode 100644 src/main/java/com/hbm/render/tileentity/RenderIndustrialTurbine.java create mode 100644 src/main/java/com/hbm/tileentity/machine/TileEntityMachineIndustrialTurbine.java create mode 100644 src/main/java/com/hbm/tileentity/machine/TileEntityTurbineBase.java diff --git a/src/main/java/com/hbm/blocks/ModBlocks.java b/src/main/java/com/hbm/blocks/ModBlocks.java index 3f8ea99fe..cf0f5c50f 100644 --- a/src/main/java/com/hbm/blocks/ModBlocks.java +++ b/src/main/java/com/hbm/blocks/ModBlocks.java @@ -968,7 +968,14 @@ public class ModBlocks { public static Block machine_steam_engine; public static Block machine_turbine; - public static Block machine_large_turbine; + @Deprecated public static Block machine_large_turbine; + public static Block machine_industrial_turbine; + public static Block machine_chungus; + + public static Block machine_condenser; + public static Block machine_tower_small; + public static Block machine_tower_large; + public static Block machine_condenser_powered; public static Block machine_deuterium_extractor; public static Block machine_deuterium_tower; @@ -979,12 +986,6 @@ public class ModBlocks { public static Block machine_compressor; public static Block machine_compressor_compact; - public static Block machine_chungus; - public static Block machine_condenser; - public static Block machine_tower_small; - public static Block machine_tower_large; - public static Block machine_condenser_powered; - public static Block machine_electrolyser; public static Block machine_excavator; @@ -2244,7 +2245,8 @@ public class ModBlocks { machine_steam_engine = new MachineSteamEngine().setBlockName("machine_steam_engine").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel"); machine_turbine = new MachineTurbine(Material.iron).setBlockName("machine_turbine").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":machine_turbine"); machine_large_turbine = new MachineLargeTurbine(Material.iron).setBlockName("machine_large_turbine").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":machine_large_turbine"); - machine_chungus = new MachineChungus(Material.iron).setBlockName("machine_chungus").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":machine_chungus"); + machine_industrial_turbine = new MachineIndustrialTurbine().setBlockName("machine_industrial_turbine").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel"); + machine_chungus = new MachineChungus().setBlockName("machine_chungus").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel"); machine_condenser = new MachineCondenser(Material.iron).setBlockName("machine_condenser").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":condenser"); machine_tower_small = new MachineTowerSmall(Material.iron).setBlockName("machine_tower_small").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":brick_concrete"); machine_tower_large = new MachineTowerLarge(Material.iron).setBlockName("machine_tower_large").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":concrete"); @@ -3282,6 +3284,7 @@ public class ModBlocks { register(machine_steam_engine); register(machine_turbine); register(machine_large_turbine); + register(machine_industrial_turbine); register(machine_chungus); GameRegistry.registerBlock(machine_condenser, machine_condenser.getUnlocalizedName()); GameRegistry.registerBlock(machine_tower_small, machine_tower_small.getUnlocalizedName()); @@ -3289,8 +3292,8 @@ public class ModBlocks { register(machine_condenser_powered); GameRegistry.registerBlock(machine_deuterium_extractor, machine_deuterium_extractor.getUnlocalizedName()); GameRegistry.registerBlock(machine_deuterium_tower, machine_deuterium_tower.getUnlocalizedName()); - GameRegistry.registerBlock(machine_liquefactor, ItemBlockBase.class, machine_liquefactor.getUnlocalizedName()); - GameRegistry.registerBlock(machine_solidifier, ItemBlockBase.class, machine_solidifier.getUnlocalizedName()); + register(machine_liquefactor); + register(machine_solidifier); register(machine_intake); register(machine_compressor); register(machine_compressor_compact); diff --git a/src/main/java/com/hbm/blocks/machine/FurnaceCombination.java b/src/main/java/com/hbm/blocks/machine/FurnaceCombination.java index 4ce96d14d..17a5d903b 100644 --- a/src/main/java/com/hbm/blocks/machine/FurnaceCombination.java +++ b/src/main/java/com/hbm/blocks/machine/FurnaceCombination.java @@ -20,8 +20,7 @@ public class FurnaceCombination extends BlockDummyable implements ITooltipProvid @Override public TileEntity createNewTileEntity(World world, int meta) { - if(meta >= 12) - return new TileEntityFurnaceCombination(); + if(meta >= 12) return new TileEntityFurnaceCombination(); return new TileEntityProxyCombo().inventory().fluid(); } diff --git a/src/main/java/com/hbm/blocks/machine/MachineChungus.java b/src/main/java/com/hbm/blocks/machine/MachineChungus.java index 16bf80634..793b5afbe 100644 --- a/src/main/java/com/hbm/blocks/machine/MachineChungus.java +++ b/src/main/java/com/hbm/blocks/machine/MachineChungus.java @@ -28,19 +28,14 @@ import net.minecraftforge.common.util.ForgeDirection; public class MachineChungus extends BlockDummyable implements ITooltipProvider, ILookOverlay { - public MachineChungus(Material mat) { - super(mat); + public MachineChungus() { + super(Material.iron); } @Override public TileEntity createNewTileEntity(World world, int meta) { - - if(meta >= 12) - return new TileEntityChungus(); - - if(meta >= 6) - return new TileEntityProxyCombo(false, true, true); - + if(meta >= 12) return new TileEntityChungus(); + if(meta >= 6) return new TileEntityProxyCombo(false, true, true); return null; } @@ -69,31 +64,7 @@ public class MachineChungus extends BlockDummyable implements ITooltipProvider, world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "hbm:block.chungusLever", 1.5F, 1.0F); if(!world.isRemote) { - FluidType type = entity.tanks[0].getTankType(); - entity.onLeverPull(type); - - if(type == Fluids.STEAM) { - entity.tanks[0].setTankType(Fluids.HOTSTEAM); - entity.tanks[1].setTankType(Fluids.STEAM); - entity.tanks[0].setFill(entity.tanks[0].getFill() / 10); - entity.tanks[1].setFill(0); - } else if(type == Fluids.HOTSTEAM) { - entity.tanks[0].setTankType(Fluids.SUPERHOTSTEAM); - entity.tanks[1].setTankType(Fluids.HOTSTEAM); - entity.tanks[0].setFill(entity.tanks[0].getFill() / 10); - entity.tanks[1].setFill(0); - } else if(type == Fluids.SUPERHOTSTEAM) { - entity.tanks[0].setTankType(Fluids.ULTRAHOTSTEAM); - entity.tanks[1].setTankType(Fluids.SUPERHOTSTEAM); - entity.tanks[0].setFill(entity.tanks[0].getFill() / 10); - entity.tanks[1].setFill(0); - } else { - entity.tanks[0].setTankType(Fluids.STEAM); - entity.tanks[1].setTankType(Fluids.SPENTSTEAM); - entity.tanks[0].setFill(Math.min(entity.tanks[0].getFill() * 1000, entity.tanks[0].getMaxFill())); - entity.tanks[1].setFill(0); - } - entity.markDirty(); + entity.onLeverPull(); } return true; @@ -168,7 +139,7 @@ public class MachineChungus extends BlockDummyable implements ITooltipProvider, text.add(EnumChatFormatting.GREEN + "-> " + EnumChatFormatting.RESET + inputType.getLocalizedName() + ": " + String.format(Locale.US, "%,d", tankInput.getFill()) + "/" + String.format(Locale.US, "%,d", tankInput.getMaxFill()) + "mB"); text.add(EnumChatFormatting.RED + "<- " + EnumChatFormatting.RESET + outputType.getLocalizedName() + ": " + String.format(Locale.US, "%,d", tankOutput.getFill()) + "/" + String.format(Locale.US, "%,d", tankOutput.getMaxFill()) + "mB"); - text.add(EnumChatFormatting.RED + "<- " + EnumChatFormatting.RESET + BobMathUtil.getShortNumber(chungus.power) + "/" + BobMathUtil.getShortNumber(chungus.getMaxPower()) + "HE"); + text.add(EnumChatFormatting.RED + "<- " + EnumChatFormatting.RESET + BobMathUtil.getShortNumber(chungus.powerBuffer) + "HE"); ILookOverlay.printGeneric(event, I18nUtil.resolveKey(getUnlocalizedName() + ".name"), 0xffff00, 0x404000, text); diff --git a/src/main/java/com/hbm/blocks/machine/MachineIndustrialTurbine.java b/src/main/java/com/hbm/blocks/machine/MachineIndustrialTurbine.java new file mode 100644 index 000000000..72da572c4 --- /dev/null +++ b/src/main/java/com/hbm/blocks/machine/MachineIndustrialTurbine.java @@ -0,0 +1,120 @@ +package com.hbm.blocks.machine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import com.hbm.blocks.BlockDummyable; +import com.hbm.blocks.ILookOverlay; +import com.hbm.blocks.ITooltipProvider; +import com.hbm.inventory.fluid.FluidType; +import com.hbm.inventory.fluid.Fluids; +import com.hbm.inventory.fluid.tank.FluidTank; +import com.hbm.inventory.fluid.trait.FT_Coolable; +import com.hbm.tileentity.TileEntityProxyCombo; +import com.hbm.tileentity.machine.TileEntityMachineIndustrialTurbine; +import com.hbm.tileentity.machine.TileEntityTurbineBase; +import com.hbm.util.BobMathUtil; +import com.hbm.util.i18n.I18nUtil; + +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderGameOverlayEvent.Pre; +import net.minecraftforge.common.util.ForgeDirection; + +public class MachineIndustrialTurbine extends BlockDummyable implements ITooltipProvider, ILookOverlay { + + public MachineIndustrialTurbine() { + super(Material.iron); + } + + @Override + public TileEntity createNewTileEntity(World world, int meta) { + if(meta >= 12) return new TileEntityMachineIndustrialTurbine(); + if(meta >= 6) return new TileEntityProxyCombo().fluid().power(); + return null; + } + + @Override + public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) { + + if(!player.isSneaking()) { + + int[] pos = this.findCore(world, x, y, z); + if(pos == null) return true; + + TileEntityTurbineBase entity = (TileEntityTurbineBase) world.getTileEntity(pos[0], pos[1], pos[2]); + if(entity != null) { + + ForgeDirection dir = ForgeDirection.getOrientation(entity.getBlockMetadata() - this.offset); + + if(x == entity.xCoord + dir.offsetX * 3 && z == entity.zCoord + dir.offsetZ * 3 && y == entity.yCoord + 1) { + world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "hbm:block.chungusLever", 1.5F, 1.0F); + if(!world.isRemote) entity.onLeverPull(); + return true; + } + } + } + + return false; + } + + @Override public int[] getDimensions() { return new int[] { 2, 0, 3, 3, 1, 1 }; } + @Override public int getOffset() { return 3; } + + @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 * o; + z += dir.offsetZ * o; + + ForgeDirection rot = dir.getRotation(ForgeDirection.UP); + + this.makeExtra(world, x + dir.offsetX * 3 + rot.offsetX, y, z + dir.offsetZ * 3 + rot.offsetZ); + this.makeExtra(world, x + dir.offsetX * 3 - rot.offsetX, y, z + dir.offsetZ * 3 - rot.offsetZ); + this.makeExtra(world, x - dir.offsetX * 1 + rot.offsetX, y, z - dir.offsetZ * 1 + rot.offsetZ); + this.makeExtra(world, x - dir.offsetX * 1 - rot.offsetX, y, z - dir.offsetZ * 1 - rot.offsetZ); + this.makeExtra(world, x + dir.offsetX * 3, y + 2, z + dir.offsetZ * 3); + this.makeExtra(world, x - dir.offsetX * 1, y + 2, z - dir.offsetZ * 1); + this.makeExtra(world, x - dir.offsetX * 3, y + 1, z - dir.offsetZ * 3); + } + + @Override + public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean ext) { + this.addStandardInfo(stack, player, list, ext); + } + + @Override + public void printHook(Pre event, World world, int x, int y, int z) { + int[] pos = this.findCore(world, x, y, z); + if(pos == null) return; + + TileEntity te = world.getTileEntity(pos[0], pos[1], pos[2]); + if(!(te instanceof TileEntityMachineIndustrialTurbine)) return; + + TileEntityMachineIndustrialTurbine chungus = (TileEntityMachineIndustrialTurbine) te; + List text = new ArrayList(); + + FluidTank tankInput = chungus.tanks[0]; + FluidTank tankOutput = chungus.tanks[1]; + + FluidType inputType = tankInput.getTankType(); + FluidType outputType = Fluids.NONE; + + if(inputType.hasTrait(FT_Coolable.class)) { + outputType = inputType.getTrait(FT_Coolable.class).coolsTo; + } + + text.add(EnumChatFormatting.GREEN + "-> " + EnumChatFormatting.RESET + inputType.getLocalizedName() + ": " + String.format(Locale.US, "%,d", tankInput.getFill()) + "/" + String.format(Locale.US, "%,d", tankInput.getMaxFill()) + "mB"); + text.add(EnumChatFormatting.RED + "<- " + EnumChatFormatting.RESET + outputType.getLocalizedName() + ": " + String.format(Locale.US, "%,d", tankOutput.getFill()) + "/" + String.format(Locale.US, "%,d", tankOutput.getMaxFill()) + "mB"); + text.add(EnumChatFormatting.RED + "<- " + EnumChatFormatting.RESET + BobMathUtil.getShortNumber(chungus.powerBuffer) + "HE (" + (int)(chungus.spin * 100) + "%)"); + + + ILookOverlay.printGeneric(event, I18nUtil.resolveKey(getUnlocalizedName() + ".name"), 0xffff00, 0x404000, text); + } +} diff --git a/src/main/java/com/hbm/blocks/machine/MachineLargeTurbine.java b/src/main/java/com/hbm/blocks/machine/MachineLargeTurbine.java index cc8328dd3..2b36ad1a1 100644 --- a/src/main/java/com/hbm/blocks/machine/MachineLargeTurbine.java +++ b/src/main/java/com/hbm/blocks/machine/MachineLargeTurbine.java @@ -17,6 +17,7 @@ import net.minecraftforge.common.util.ForgeDirection; import java.util.List; +@Deprecated public class MachineLargeTurbine extends BlockDummyable implements ITooltipProvider { public MachineLargeTurbine(Material mat) { diff --git a/src/main/java/com/hbm/entity/mob/EntityFBI.java b/src/main/java/com/hbm/entity/mob/EntityFBI.java index a20e5c415..c1f29e7a4 100644 --- a/src/main/java/com/hbm/entity/mob/EntityFBI.java +++ b/src/main/java/com/hbm/entity/mob/EntityFBI.java @@ -150,10 +150,13 @@ public class EntityFBI extends EntityMob implements IRangedAttackMob { canDestroy.add(Blocks.trapdoor); canDestroy.add(ModBlocks.machine_press); canDestroy.add(ModBlocks.machine_epress); - canDestroy.add(ModBlocks.machine_chemplant); + canDestroy.add(ModBlocks.machine_chemical_plant); + canDestroy.add(ModBlocks.machine_chemical_factory); canDestroy.add(ModBlocks.machine_crystallizer); canDestroy.add(ModBlocks.machine_turbine); - canDestroy.add(ModBlocks.machine_large_turbine); + canDestroy.add(ModBlocks.machine_industrial_turbine); + canDestroy.add(ModBlocks.machine_chungus); + canDestroy.add(ModBlocks.machine_purex); canDestroy.add(ModBlocks.crate_iron); canDestroy.add(ModBlocks.crate_steel); canDestroy.add(ModBlocks.machine_diesel); diff --git a/src/main/java/com/hbm/inventory/recipes/AssemblyMachineRecipes.java b/src/main/java/com/hbm/inventory/recipes/AssemblyMachineRecipes.java index 5d775ed67..78a78b1b8 100644 --- a/src/main/java/com/hbm/inventory/recipes/AssemblyMachineRecipes.java +++ b/src/main/java/com/hbm/inventory/recipes/AssemblyMachineRecipes.java @@ -386,8 +386,8 @@ public class AssemblyMachineRecipes extends GenericRecipes { this.register(new GenericRecipe("ass.hephaestus").setup(200, 100).outputItems(new ItemStack(ModBlocks.machine_hephaestus, 1)) .inputItems(new OreDictStack(STEEL.pipe(), 12), new OreDictStack(STEEL.ingot(), 24), new OreDictStack(CU.plate(), 24), new OreDictStack(NB.ingot(), 4), new OreDictStack(RUBBER.ingot(), 12), new ComparableStack(ModBlocks.glass_quartz, 16)) .inputItemsEx(new ComparableStack(ModItems.item_expensive, 8, EnumExpensiveType.HEAVY_FRAME), new OreDictStack(NB.ingot(), 16), new OreDictStack(RUBBER.ingot(), 16), new ComparableStack(ModBlocks.glass_quartz, 16))); - this.register(new GenericRecipe("ass.iturbine").setup(200, 100).outputItems(new ItemStack(ModBlocks.machine_large_turbine, 1)) - .inputItems(new OreDictStack(STEEL.plate(), 12), new OreDictStack(RUBBER.ingot(), 4), new ComparableStack(ModItems.turbine_titanium, 3), new OreDictStack(GOLD.wireDense(), 6), new OreDictStack(DURA.pipe(), 3), new OreDictStack(STEEL.pipe(), 4), new ComparableStack(ModItems.circuit, 4, EnumCircuitType.BASIC)) + this.register(new GenericRecipe("ass.iturbine").setup(200, 100).outputItems(new ItemStack(ModBlocks.machine_industrial_turbine, 1)) + .inputItems(new OreDictStack(STEEL.plate(), 12), new OreDictStack(RUBBER.ingot(), 4), new ComparableStack(ModItems.turbine_titanium, 3), new OreDictStack(GOLD.wireDense(), 6), new OreDictStack(DURA.pipe(), 4), new ComparableStack(ModItems.circuit, 4, EnumCircuitType.BASIC)) .inputItemsEx(new ComparableStack(ModItems.item_expensive, 4, EnumExpensiveType.HEAVY_FRAME), new ComparableStack(ModItems.turbine_titanium, 3), new OreDictStack(GOLD.wireDense(), 16), new OreDictStack(DURA.pipe(), 16), new ComparableStack(ModItems.item_expensive, 3, EnumExpensiveType.CIRCUIT))); this.register(new GenericRecipe("ass.leviturbine").setup(600, 100).outputItems(new ItemStack(ModBlocks.machine_chungus, 1)) .inputItems(new OreDictStack(STEEL.shell(), 6), new OreDictStack(STEEL.plateWelded(), 16), new OreDictStack(TI.plate(), 12), new OreDictStack(ANY_RESISTANTALLOY.ingot(), 16), new ComparableStack(ModItems.turbine_tungsten, 5), new ComparableStack(ModItems.turbine_titanium, 3), new ComparableStack(ModItems.flywheel_beryllium, 1), new OreDictStack(GOLD.wireDense(), 48), new OreDictStack(DURA.pipe(), 16), new OreDictStack(STEEL.pipe(), 16)) diff --git a/src/main/java/com/hbm/main/ClientProxy.java b/src/main/java/com/hbm/main/ClientProxy.java index 115b054f8..366757216 100644 --- a/src/main/java/com/hbm/main/ClientProxy.java +++ b/src/main/java/com/hbm/main/ClientProxy.java @@ -312,6 +312,7 @@ public class ClientProxy extends ServerProxy { ClientRegistry.bindTileEntitySpecialRenderer(TileEntityBatterySocket.class, new RenderBatterySocket()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityBatteryREDD.class, new RenderBatteryREDD()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineLargeTurbine.class, new RenderBigTurbine()); + ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineIndustrialTurbine.class, new RenderIndustrialTurbine()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineReactorBreeding.class, new RenderBreeder()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntitySolarBoiler.class, new RenderSolarBoiler()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityStorageDrum.class, new RenderStorageDrum()); diff --git a/src/main/java/com/hbm/main/ResourceManager.java b/src/main/java/com/hbm/main/ResourceManager.java index 669eaa662..4f6444ddf 100644 --- a/src/main/java/com/hbm/main/ResourceManager.java +++ b/src/main/java/com/hbm/main/ResourceManager.java @@ -105,9 +105,10 @@ public class ResourceManager { public static final IModelCustom pump = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/pump.obj")).asVBO(); //Large Turbine - public static final IModelCustom steam_engine = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/steam_engine.obj")).asVBO(); - public static final IModelCustom turbine = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/turbine.obj")); - public static final IModelCustom chungus = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/chungus.obj")).asVBO(); + public static final IModelCustom steam_engine = new HFRWavefrontObject("models/machines/steam_engine.obj").asVBO(); + public static final IModelCustom turbine = new HFRWavefrontObject("models/machines/turbine.obj").asVBO(); + public static final IModelCustom industrial_turbine = new HFRWavefrontObject("models/machines/industrial_turbine.obj").asVBO(); + public static final IModelCustom chungus = new HFRWavefrontObject("models/machines/chungus.obj").asVBO(); //Cooling Tower public static final IModelCustom tower_small = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/tower_small.obj")).asVBO(); @@ -118,13 +119,13 @@ public class ResourceManager { public static final IModelCustom condenser = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/condenser.obj")).asVBO(); //Wood burner - public static final IModelCustom wood_burner = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/wood_burner.obj")); + public static final IModelCustom wood_burner = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/wood_burner.obj")).asVBO(); //IGen public static final IModelCustom igen = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/igen.obj")); //Combustion Engine - public static final IModelCustom dieselgen = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/dieselgen.obj")); + public static final IModelCustom dieselgen = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/dieselgen.obj")).asVBO(); public static final IModelCustom combustion_engine = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/combustion_engine.obj")).asVBO(); //Press @@ -159,7 +160,7 @@ public class ResourceManager { public static final IModelCustom purex = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/purex.obj")).asVBO(); //Mixer - public static final IModelCustom mixer = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/mixer.obj")); + public static final IModelCustom mixer = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/mixer.obj")).asVBO(); //Arc Welder public static final IModelCustom arc_welder = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/arc_welder.obj"), false).asVBO(); @@ -183,7 +184,7 @@ public class ResourceManager { public static final IModelCustom microwave = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/machines/microwave.obj")); //Big Man Johnson - public static final IModelCustom autosaw = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/machines/autosaw.obj")); + public static final IModelCustom autosaw = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/autosaw.obj"), false).asVBO(); //Mining Drill public static final IModelCustom mining_drill = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/machines/mining_drill.obj")).asVBO(); @@ -546,6 +547,7 @@ public class ResourceManager { //Large Turbine public static final ResourceLocation steam_engine_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/steam_engine.png"); public static final ResourceLocation turbine_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/turbine.png"); + public static final ResourceLocation industrial_turbine_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/industrial_turbine.png"); public static final ResourceLocation chungus_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/chungus.png"); //Cooling Tower diff --git a/src/main/java/com/hbm/render/loader/HFRWavefrontObject.java b/src/main/java/com/hbm/render/loader/HFRWavefrontObject.java index 2b65efee2..df9af98ff 100644 --- a/src/main/java/com/hbm/render/loader/HFRWavefrontObject.java +++ b/src/main/java/com/hbm/render/loader/HFRWavefrontObject.java @@ -13,6 +13,8 @@ import java.util.regex.Pattern; import org.lwjgl.opengl.GL11; +import com.hbm.lib.RefStrings; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.client.Minecraft; @@ -51,6 +53,15 @@ public class HFRWavefrontObject implements IModelCustomNamed { private String fileName; private boolean smoothing = true; + public HFRWavefrontObject(String name) throws ModelFormatException { + this(new ResourceLocation(RefStrings.MODID, name)); + } + + public HFRWavefrontObject noSmooth() { + this.smoothing = false; + return this; + } + public HFRWavefrontObject(ResourceLocation resource) throws ModelFormatException { this.resource = resource; this.fileName = resource.toString(); diff --git a/src/main/java/com/hbm/render/tileentity/RenderIndustrialTurbine.java b/src/main/java/com/hbm/render/tileentity/RenderIndustrialTurbine.java new file mode 100644 index 000000000..f412f7171 --- /dev/null +++ b/src/main/java/com/hbm/render/tileentity/RenderIndustrialTurbine.java @@ -0,0 +1,92 @@ +package com.hbm.render.tileentity; + +import org.lwjgl.opengl.GL11; + +import com.hbm.blocks.ModBlocks; +import com.hbm.inventory.fluid.Fluids; +import com.hbm.main.ResourceManager; +import com.hbm.render.item.ItemRenderBase; +import com.hbm.tileentity.machine.TileEntityMachineIndustrialTurbine; + +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.item.Item; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.client.IItemRenderer; + +public class RenderIndustrialTurbine extends TileEntitySpecialRenderer implements IItemRendererProvider { + + @Override + public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float interp) { + GL11.glPushMatrix(); + GL11.glTranslated(x + 0.5, y, z + 0.5); + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_CULL_FACE); + GL11.glShadeModel(GL11.GL_SMOOTH); + + switch(tile.getBlockMetadata() - 10) { + case 2: GL11.glRotatef(180, 0F, 1F, 0F); break; + case 4: GL11.glRotatef(270, 0F, 1F, 0F); break; + case 3: GL11.glRotatef(0, 0F, 1F, 0F); break; + case 5: GL11.glRotatef(90, 0F, 1F, 0F); break; + } + + TileEntityMachineIndustrialTurbine turbine = (TileEntityMachineIndustrialTurbine) tile; + + bindTexture(ResourceManager.industrial_turbine_tex); + ResourceManager.industrial_turbine.renderPart("Turbine"); + + GL11.glPushMatrix(); + GL11.glTranslated(0, 1.5, 0); + GL11.glRotated(135 - (turbine.tanks[0].getTankType().getID() - Fluids.STEAM.getID()) * 90, 0, 0, 1); + GL11.glTranslated(0, -1.5, 0); + ResourceManager.industrial_turbine.renderPart("Gauge"); + GL11.glPopMatrix(); + + GL11.glPushMatrix(); + GL11.glTranslated(0, 1.5, 0); + GL11.glRotated(turbine.lastRotor + (turbine.rotor - turbine.lastRotor) * interp, 0, 0, -1); + GL11.glTranslated(0, -1.5, 0); + ResourceManager.industrial_turbine.renderPart("Flywheel"); + GL11.glPopMatrix(); + + GL11.glShadeModel(GL11.GL_FLAT); + GL11.glPopMatrix(); + } + + @Override + public Item getItemForRenderer() { + return Item.getItemFromBlock(ModBlocks.machine_industrial_turbine); + } + + @Override + public IItemRenderer getRenderer() { + return new ItemRenderBase( ) { + public void renderInventory() { + GL11.glTranslated(1, 0, 0); + GL11.glScaled(3, 3, 3); + } + public void renderCommon() { + GL11.glRotatef(90, 0F, 1F, 0F); + GL11.glScaled(0.75, 0.75, 0.75); + GL11.glTranslated(0.5, 0, 0); + GL11.glShadeModel(GL11.GL_SMOOTH); + bindTexture(ResourceManager.industrial_turbine_tex); + + ResourceManager.industrial_turbine.renderPart("Turbine"); + + GL11.glTranslated(0, 1.5, 0); + GL11.glRotated(135, 0, 0, 1); + GL11.glTranslated(0, -1.5, 0); + ResourceManager.industrial_turbine.renderPart("Gauge"); + + double rot = (System.currentTimeMillis() / 5) % 336D; + GL11.glTranslated(0, 1.5, 0); + GL11.glRotated(rot, 0, 0, -1); + GL11.glTranslated(0, -1.5, 0); + ResourceManager.industrial_turbine.renderPart("Flywheel"); + + GL11.glShadeModel(GL11.GL_FLAT); + } + }; + } +} diff --git a/src/main/java/com/hbm/tileentity/TileEntityProxyCombo.java b/src/main/java/com/hbm/tileentity/TileEntityProxyCombo.java index 9a7ee5cfb..2eb2b5081 100644 --- a/src/main/java/com/hbm/tileentity/TileEntityProxyCombo.java +++ b/src/main/java/com/hbm/tileentity/TileEntityProxyCombo.java @@ -7,6 +7,7 @@ import com.hbm.inventory.fluid.FluidType; import com.hbm.inventory.fluid.tank.FluidTank; import api.hbm.energymk2.IEnergyConductorMK2; +import api.hbm.energymk2.IEnergyConnectorMK2; import api.hbm.energymk2.IEnergyReceiverMK2; import api.hbm.fluidmk2.IFluidConnectorMK2; import api.hbm.fluidmk2.IFluidReceiverMK2; @@ -148,15 +149,15 @@ public class TileEntityProxyCombo extends TileEntityProxyBase implements IEnergy @Override public boolean canConnect(ForgeDirection dir) { - if(power && getCoreObject() instanceof IEnergyReceiverMK2) { - return ((IEnergyReceiverMK2)getCoreObject()).canConnect(dir); + if(power && getCoreObject() instanceof IEnergyConnectorMK2) { + return ((IEnergyConnectorMK2)getCoreObject()).canConnect(dir); } if(conductor && getCoreObject() instanceof IEnergyConductorMK2) { return ((IEnergyConductorMK2)getCoreObject()).canConnect(dir); } - return true; + return false; } @Override diff --git a/src/main/java/com/hbm/tileentity/TileMappings.java b/src/main/java/com/hbm/tileentity/TileMappings.java index 0b89cb049..6a8791bdf 100644 --- a/src/main/java/com/hbm/tileentity/TileMappings.java +++ b/src/main/java/com/hbm/tileentity/TileMappings.java @@ -347,6 +347,7 @@ public class TileMappings { put(TileEntitySteamEngine.class, "tileentity_steam_engine"); put(TileEntityMachineTurbine.class, "tileentity_turbine"); put(TileEntityMachineLargeTurbine.class, "tileentity_industrial_turbine"); + put(TileEntityMachineIndustrialTurbine.class, "tileentity_ind_turbine"); put(TileEntityChungus.class, "tileentity_chungus"); put(TileEntityMachineCombustionEngine.class, "tileentity_combustion_engine"); diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityChungus.java b/src/main/java/com/hbm/tileentity/machine/TileEntityChungus.java index c5c922c8f..0b367a1d6 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityChungus.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityChungus.java @@ -7,54 +7,35 @@ import com.google.gson.JsonObject; import com.google.gson.stream.JsonWriter; import com.hbm.blocks.BlockDummyable; import com.hbm.handler.CompatHandler; -import com.hbm.inventory.fluid.FluidType; import com.hbm.inventory.fluid.Fluids; import com.hbm.inventory.fluid.tank.FluidTank; -import com.hbm.inventory.fluid.trait.FT_Coolable; -import com.hbm.inventory.fluid.trait.FT_Coolable.CoolingType; import com.hbm.main.MainRegistry; import com.hbm.sound.AudioWrapper; -import com.hbm.tileentity.IBufPacketReceiver; -import com.hbm.tileentity.IFluidCopiable; import com.hbm.tileentity.IConfigurableMachine; -import com.hbm.tileentity.TileEntityLoadedBase; -import com.hbm.util.CompatEnergyControl; -import com.hbm.util.fauxpointtwelve.BlockPos; import com.hbm.util.fauxpointtwelve.DirPos; -import api.hbm.energymk2.IEnergyProviderMK2; -import api.hbm.fluid.IFluidStandardTransceiver; -import api.hbm.tile.IInfoProviderEC; import cpw.mods.fml.common.Optional; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; import io.netty.buffer.ByteBuf; import li.cil.oc.api.machine.Arguments; import li.cil.oc.api.machine.Callback; import li.cil.oc.api.machine.Context; import li.cil.oc.api.network.SimpleComponent; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraftforge.common.util.ForgeDirection; @Optional.InterfaceList({@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "OpenComputers")}) -public class TileEntityChungus extends TileEntityLoadedBase implements IEnergyProviderMK2, IFluidStandardTransceiver, SimpleComponent, IInfoProviderEC, CompatHandler.OCComponent, IConfigurableMachine, IBufPacketReceiver, IFluidCopiable{ +public class TileEntityChungus extends TileEntityTurbineBase implements SimpleComponent, CompatHandler.OCComponent, IConfigurableMachine { - public long power; private int turnTimer; public float rotor; public float lastRotor; public float fanAcceleration = 0F; - public FluidTank[] tanks; - protected double[] info = new double[3]; - private AudioWrapper audio; private float audioDesync; //Configurable values - public static long maxPower = 100000000000L; public static int inputTankSize = 1_000_000_000; public static int outputTankSize = 1_000_000_000; public static double efficiency = 0.85D; @@ -75,7 +56,6 @@ public class TileEntityChungus extends TileEntityLoadedBase implements IEnergyPr @Override public void readIfPresent(JsonObject obj) { - maxPower = IConfigurableMachine.grab(obj, "L:maxPower", maxPower); inputTankSize = IConfigurableMachine.grab(obj, "I:inputTankSize", inputTankSize); outputTankSize = IConfigurableMachine.grab(obj, "I:outputTankSize", outputTankSize); efficiency = IConfigurableMachine.grab(obj, "D:efficiency", efficiency); @@ -83,123 +63,16 @@ public class TileEntityChungus extends TileEntityLoadedBase implements IEnergyPr @Override public void writeConfig(JsonWriter writer) throws IOException { - writer.name("L:maxPower").value(maxPower); writer.name("INFO").value("leviathan steam turbine consumes all availible steam per tick"); writer.name("I:inputTankSize").value(inputTankSize); writer.name("I:outputTankSize").value(outputTankSize); writer.name("D:efficiency").value(efficiency); } - - + + @Override public double consumptionPercent() { return 1D; } + @Override public double getEfficiency() { return efficiency; } @Override - public void updateEntity() { - - if(!worldObj.isRemote) { - - this.power *= 0.95; - - this.info = new double[3]; - - boolean operational = false; - FluidType in = tanks[0].getTankType(); - boolean valid = false; - if(in.hasTrait(FT_Coolable.class)) { - FT_Coolable trait = in.getTrait(FT_Coolable.class); - double eff = trait.getEfficiency(CoolingType.TURBINE) * efficiency; //85% efficiency by default - if(eff > 0) { - tanks[1].setTankType(trait.coolsTo); - int inputOps = tanks[0].getFill() / trait.amountReq; - int outputOps = (tanks[1].getMaxFill() - tanks[1].getFill()) / trait.amountProduced; - int ops = Math.min(inputOps, outputOps); - tanks[0].setFill(tanks[0].getFill() - ops * trait.amountReq); - tanks[1].setFill(tanks[1].getFill() + ops * trait.amountProduced); - this.power += (ops * trait.heatEnergy * eff); - info[0] = ops * trait.amountReq; - info[1] = ops * trait.amountProduced; - info[2] = ops * trait.heatEnergy * eff; - valid = true; - operational = ops > 0; - } - } - - if(!valid) tanks[1].setTankType(Fluids.NONE); - if(power > maxPower) power = maxPower; - - ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - BlockDummyable.offset); - this.tryProvide(worldObj, xCoord - dir.offsetX * 11, yCoord, zCoord - dir.offsetZ * 11, dir.getOpposite()); - - for(DirPos pos : this.getConPos()) { - this.sendFluid(tanks[1], worldObj, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); - this.trySubscribe(tanks[0].getTankType(), worldObj, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); - } - - if(power > maxPower) - power = maxPower; - - turnTimer--; - - if(operational) turnTimer = 25; - networkPackNT(150); - - } else { - - this.lastRotor = this.rotor; - this.rotor += this.fanAcceleration; - - if(this.rotor >= 360) { - this.rotor -= 360; - this.lastRotor -= 360; - } - - if(turnTimer > 0) { - // Fan accelerates with a random offset to ensure the audio doesn't perfectly align, makes for a more pleasant hum - this.fanAcceleration = Math.max(0F, Math.min(25F, this.fanAcceleration += 0.075F + audioDesync)); - - Random rand = worldObj.rand; - ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - BlockDummyable.offset); - ForgeDirection side = dir.getRotation(ForgeDirection.UP); - - for(int i = 0; i < 10; i++) { - worldObj.spawnParticle("cloud", - xCoord + 0.5 + dir.offsetX * (rand.nextDouble() + 1.25) + rand.nextGaussian() * side.offsetX * 0.65, - yCoord + 2.5 + rand.nextGaussian() * 0.65, - zCoord + 0.5 + dir.offsetZ * (rand.nextDouble() + 1.25) + rand.nextGaussian() * side.offsetZ * 0.65, - -dir.offsetX * 0.2, 0, -dir.offsetZ * 0.2); - } - - - if(audio == null) { - audio = MainRegistry.proxy.getLoopedSound("hbm:block.chungusTurbineRunning", xCoord, yCoord, zCoord, 1.0F, 20F, 1.0F); - audio.startSound(); - } - - float turbineSpeed = this.fanAcceleration / 25F; - audio.updateVolume(getVolume(0.5f * turbineSpeed)); - audio.updatePitch(0.25F + 0.75F * turbineSpeed); - } else { - this.fanAcceleration = Math.max(0F, Math.min(25F, this.fanAcceleration -= 0.1F)); - - if(audio != null) { - if(this.fanAcceleration > 0) { - float turbineSpeed = this.fanAcceleration / 25F; - audio.updateVolume(getVolume(0.5f * turbineSpeed)); - audio.updatePitch(0.25F + 0.75F * turbineSpeed); - } else { - audio.stopSound(); - audio = null; - } - } - } - } - } - - public void onLeverPull(FluidType previous) { - for(BlockPos pos : getConPos()) { - this.tryUnsubscribe(previous, worldObj, pos.getX(), pos.getY(), pos.getZ()); - } - } - public DirPos[] getConPos() { ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - BlockDummyable.offset); ForgeDirection rot = dir.getRotation(ForgeDirection.UP); @@ -209,37 +82,82 @@ public class TileEntityChungus extends TileEntityLoadedBase implements IEnergyPr new DirPos(xCoord - rot.offsetX * 3, yCoord, zCoord - rot.offsetZ * 3, rot.getOpposite()) }; } + + @Override + public DirPos[] getPowerPos() { + ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - BlockDummyable.offset); + return new DirPos[] { new DirPos(xCoord - dir.offsetX * 11, yCoord, zCoord - dir.offsetZ * 11, dir.getOpposite()) }; + } + + @Override + public void onServerTick() { + turnTimer--; + if(operational) turnTimer = 25; + } + + @Override + public void onClientTick() { + + this.lastRotor = this.rotor; + this.rotor += this.fanAcceleration; + + if(this.rotor >= 360) { + this.rotor -= 360; + this.lastRotor -= 360; + } + + if(turnTimer > 0) { + // Fan accelerates with a random offset to ensure the audio doesn't perfectly align, makes for a more pleasant hum + this.fanAcceleration = Math.max(0F, Math.min(25F, this.fanAcceleration += 0.075F + audioDesync)); + + Random rand = worldObj.rand; + ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - BlockDummyable.offset); + ForgeDirection side = dir.getRotation(ForgeDirection.UP); + + for(int i = 0; i < 10; i++) { + worldObj.spawnParticle("cloud", + xCoord + 0.5 + dir.offsetX * (rand.nextDouble() + 1.25) + rand.nextGaussian() * side.offsetX * 0.65, + yCoord + 2.5 + rand.nextGaussian() * 0.65, + zCoord + 0.5 + dir.offsetZ * (rand.nextDouble() + 1.25) + rand.nextGaussian() * side.offsetZ * 0.65, + -dir.offsetX * 0.2, 0, -dir.offsetZ * 0.2); + } + + if(audio == null) { + audio = MainRegistry.proxy.getLoopedSound("hbm:block.chungusTurbineRunning", xCoord, yCoord, zCoord, 1.0F, 20F, 1.0F, 20); + audio.startSound(); + } + + float turbineSpeed = this.fanAcceleration / 25F; + audio.updateVolume(getVolume(0.5f * turbineSpeed)); + audio.updatePitch(0.25F + 0.75F * turbineSpeed); + audio.keepAlive(); + + } else { + this.fanAcceleration = Math.max(0F, Math.min(25F, this.fanAcceleration -= 0.1F)); + + if(audio != null) { + if(this.fanAcceleration > 0) { + float turbineSpeed = this.fanAcceleration / 25F; + audio.updateVolume(getVolume(0.5f * turbineSpeed)); + audio.updatePitch(0.25F + 0.75F * turbineSpeed); + } else { + audio.stopSound(); + audio = null; + } + } + } + } @Override public void serialize(ByteBuf buf) { - buf.writeLong(this.power); + super.serialize(buf); buf.writeInt(this.turnTimer); - this.tanks[0].serialize(buf); - this.tanks[1].serialize(buf); } @Override public void deserialize(ByteBuf buf) { - this.power = buf.readLong(); + super.deserialize(buf); this.turnTimer = buf.readInt(); - this.tanks[0].deserialize(buf); - this.tanks[1].deserialize(buf); - } - - @Override - public void readFromNBT(NBTTagCompound nbt) { - super.readFromNBT(nbt); - tanks[0].readFromNBT(nbt, "water"); - tanks[1].readFromNBT(nbt, "steam"); - power = nbt.getLong("power"); - } - - @Override - public void writeToNBT(NBTTagCompound nbt) { - super.writeToNBT(nbt); - tanks[0].writeToNBT(nbt, "water"); - tanks[1].writeToNBT(nbt, "steam"); - nbt.setLong("power", power); } @Override @@ -247,32 +165,11 @@ public class TileEntityChungus extends TileEntityLoadedBase implements IEnergyPr return TileEntity.INFINITE_EXTENT_AABB; } - @Override - @SideOnly(Side.CLIENT) - public double getMaxRenderDistanceSquared() { - return 65536.0D; - } - @Override public boolean canConnect(ForgeDirection dir) { return dir != ForgeDirection.UP && dir != ForgeDirection.DOWN && dir != ForgeDirection.UNKNOWN; } - @Override - public long getPower() { - return power; - } - - @Override - public long getMaxPower() { - return maxPower; - } - - @Override - public void setPower(long power) { - this.power = power; - } - @Override @Optional.Method(modid = "OpenComputers") public String getComponentName() { @@ -321,13 +218,13 @@ public class TileEntityChungus extends TileEntityLoadedBase implements IEnergyPr @Callback(direct = true, doc = "function():number -- Gets the power buffer of the turbine.") @Optional.Method(modid = "OpenComputers") public Object[] getPower(Context context, Arguments args) { - return new Object[] {power}; + return new Object[] {powerBuffer}; } @Callback(direct = true, doc = "function():table -- Gets information about this turbine. The format is the following: , , , , , ") @Optional.Method(modid = "OpenComputers") public Object[] getInfo(Context context, Arguments args) { - return new Object[] {tanks[0].getFill(), tanks[0].getMaxFill(), tanks[1].getFill(), tanks[1].getMaxFill(), CompatHandler.steamTypeToInt(tanks[0].getTankType())[0], power}; + return new Object[] {tanks[0].getFill(), tanks[0].getMaxFill(), tanks[1].getFill(), tanks[1].getMaxFill(), CompatHandler.steamTypeToInt(tanks[0].getTankType())[0], powerBuffer}; } @Override @@ -357,34 +254,6 @@ public class TileEntityChungus extends TileEntityLoadedBase implements IEnergyPr case ("getInfo"): return getInfo(context, args); } - throw new NoSuchMethodException(); - } - - @Override - public FluidTank[] getSendingTanks() { - return new FluidTank[] {tanks[1]}; - } - - @Override - public FluidTank[] getReceivingTanks() { - return new FluidTank[] {tanks[0]}; - } - - @Override - public FluidTank[] getAllTanks() { - return tanks; - } - - @Override - public void provideExtraInfo(NBTTagCompound data) { - data.setBoolean(CompatEnergyControl.B_ACTIVE, info[1] > 0); - data.setDouble(CompatEnergyControl.D_CONSUMPTION_MB, info[0]); - data.setDouble(CompatEnergyControl.D_OUTPUT_MB, info[1]); - data.setDouble(CompatEnergyControl.D_OUTPUT_HE, info[2]); - } - - @Override - public FluidTank getTankToPaste() { - return null; + throw new NoSuchMethodException(); } } diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineIndustrialTurbine.java b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineIndustrialTurbine.java new file mode 100644 index 000000000..7c2045a71 --- /dev/null +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineIndustrialTurbine.java @@ -0,0 +1,163 @@ +package com.hbm.tileentity.machine; + +import java.io.IOException; + +import com.google.gson.JsonObject; +import com.google.gson.stream.JsonWriter; +import com.hbm.blocks.BlockDummyable; +import com.hbm.inventory.fluid.FluidType; +import com.hbm.inventory.fluid.Fluids; +import com.hbm.inventory.fluid.tank.FluidTank; +import com.hbm.inventory.fluid.trait.FT_Coolable; +import com.hbm.inventory.fluid.trait.FT_Coolable.CoolingType; +import com.hbm.tileentity.IConfigurableMachine; +import com.hbm.util.fauxpointtwelve.DirPos; + +import io.netty.buffer.ByteBuf; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.util.ForgeDirection; + +public class TileEntityMachineIndustrialTurbine extends TileEntityTurbineBase implements IConfigurableMachine { + + public static int inputTankSize = 1_000_000_000; + public static int outputTankSize = 1_000_000_000; + public static double efficiency = 1D; + + public float rotor; + public float lastRotor; + + public double spin = 0; + public static double ACCELERATION = 1D / 400D; + public long lastPowerTarget = 0; + + @Override + public String getConfigName() { + return "steamturbineIndustrial"; + } + + @Override + public void readIfPresent(JsonObject obj) { + inputTankSize = IConfigurableMachine.grab(obj, "I:inputTankSize", inputTankSize); + outputTankSize = IConfigurableMachine.grab(obj, "I:outputTankSize", outputTankSize); + efficiency = IConfigurableMachine.grab(obj, "D:efficiency", efficiency); + } + + @Override + public void writeConfig(JsonWriter writer) throws IOException { + writer.name("INFO").value("industrial steam turbine consumes 20% of availible steam per tick"); + writer.name("I:inputTankSize").value(inputTankSize); + writer.name("I:outputTankSize").value(outputTankSize); + writer.name("D:efficiency").value(efficiency); + } + + public TileEntityMachineIndustrialTurbine() { + tanks = new FluidTank[2]; + tanks[0] = new FluidTank(Fluids.STEAM, inputTankSize); + tanks[1] = new FluidTank(Fluids.SPENTSTEAM, outputTankSize); + } + + // sets the power target so we know how much this steam type can theoretically make, and increments the spin based on actual throughput + @Override + public void generatePower(long power, int steamConsumed) { + FT_Coolable trait = tanks[0].getTankType().getTrait(FT_Coolable.class); + double eff = trait.getEfficiency(CoolingType.TURBINE) * getEfficiency(); + int maxOps = (int) Math.ceil((tanks[0].getMaxFill() * consumptionPercent()) / trait.amountReq); + this.lastPowerTarget = (long) (maxOps * trait.heatEnergy * eff); // theoretical max output at full blast with this type + double fraction = (double) steamConsumed / (double) (trait.amountReq * maxOps); // % of max steam throughput currently achieved + + if(Math.abs(spin - fraction) <= ACCELERATION) { + this.spin = fraction; + } else if(spin < fraction) { + this.spin += ACCELERATION; + } else if(spin > fraction) { + this.spin -= ACCELERATION; + } + } + + @Override + public void onServerTick() { + if(!operational) { + this.spin -= ACCELERATION; + } + + if(this.spin <= 0) { + this.spin = 0; + } else { + this.powerBuffer = (long) (this.lastPowerTarget * this.spin); + } + } + + @Override + public void onClientTick() { + + this.lastRotor = this.rotor; + this.rotor += this.spin * 30; + + if(this.rotor >= 360) { + this.lastRotor -= 360; + this.rotor -= 360; + } + } + + @Override + public boolean canConnect(ForgeDirection dir) { + ForgeDirection myDir = ForgeDirection.getOrientation(this.getBlockMetadata() - BlockDummyable.offset); + return dir == myDir.getOpposite(); + } + + @Override + public boolean canConnect(FluidType type, ForgeDirection dir) { + if(!type.hasTrait(FT_Coolable.class)) return false; + ForgeDirection myDir = ForgeDirection.getOrientation(this.getBlockMetadata() - BlockDummyable.offset); + return dir != myDir && dir != myDir.getOpposite(); + } + + @Override public double consumptionPercent() { return 0.2D; } + @Override public double getEfficiency() { return efficiency; } + + @Override + public void serialize(ByteBuf buf) { + super.serialize(buf); + buf.writeDouble(this.spin); + } + + @Override + public void deserialize(ByteBuf buf) { + super.deserialize(buf); + this.spin = buf.readDouble(); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + lastPowerTarget = nbt.getLong("lastPowerTarget"); + } + + @Override + public void writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + nbt.setLong("lastPowerTarget", lastPowerTarget); + } + + @Override + public DirPos[] getConPos() { + ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - BlockDummyable.offset); + ForgeDirection rot = dir.getRotation(ForgeDirection.UP); + return new DirPos[] { + new DirPos(xCoord + dir.offsetX * 3 + rot.offsetX * 2, yCoord, zCoord + dir.offsetZ * 3 + rot.offsetZ * 2, rot), + new DirPos(xCoord + dir.offsetX * 3 - rot.offsetX * 2, yCoord, zCoord + dir.offsetZ * 3 - rot.offsetZ * 2, rot.getOpposite()), + new DirPos(xCoord - dir.offsetX * 1 + rot.offsetX * 2, yCoord, zCoord - dir.offsetZ * 1 + rot.offsetZ * 2, rot), + new DirPos(xCoord - dir.offsetX * 1 - rot.offsetX * 2, yCoord, zCoord - dir.offsetZ * 1 - rot.offsetZ * 2, rot.getOpposite()), + new DirPos(xCoord + dir.offsetX * 3, yCoord + 3, zCoord + dir.offsetZ * 3, ForgeDirection.UP), + new DirPos(xCoord - dir.offsetX * 1, yCoord + 3, zCoord - dir.offsetZ * 1, ForgeDirection.UP), + }; + } + + @Override + public DirPos[] getPowerPos() { + ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata() - BlockDummyable.offset); + return new DirPos[] { + new DirPos(xCoord - dir.offsetX * 4, yCoord + 1, zCoord - dir.offsetZ * 4, dir.getOpposite()) + }; + } +} diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineLargeTurbine.java b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineLargeTurbine.java index 33f318fb1..28c9ab943 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineLargeTurbine.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineLargeTurbine.java @@ -1,10 +1,7 @@ package com.hbm.tileentity.machine; import java.util.Random; -import java.io.IOException; -import com.google.gson.JsonObject; -import com.google.gson.stream.JsonWriter; import com.hbm.blocks.BlockDummyable; import com.hbm.handler.CompatHandler; import com.hbm.inventory.container.ContainerMachineLargeTurbine; @@ -18,7 +15,6 @@ import com.hbm.lib.Library; import com.hbm.main.MainRegistry; import com.hbm.sound.AudioWrapper; import com.hbm.tileentity.IFluidCopiable; -import com.hbm.tileentity.IConfigurableMachine; import com.hbm.tileentity.IGUIProvider; import com.hbm.tileentity.TileEntityMachineBase; import com.hbm.util.CompatEnergyControl; @@ -44,7 +40,7 @@ import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; @Optional.InterfaceList({@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "OpenComputers")}) -public class TileEntityMachineLargeTurbine extends TileEntityMachineBase implements IEnergyProviderMK2, IFluidStandardTransceiver, IGUIProvider, SimpleComponent, IInfoProviderEC, CompatHandler.OCComponent, IConfigurableMachine, IFluidCopiable { +public class TileEntityMachineLargeTurbine extends TileEntityMachineBase implements IEnergyProviderMK2, IFluidStandardTransceiver, IGUIProvider, SimpleComponent, IInfoProviderEC, CompatHandler.OCComponent, IFluidCopiable { public long power; public FluidTank[] tanks; @@ -76,28 +72,6 @@ public class TileEntityMachineLargeTurbine extends TileEntityMachineBase impleme audioDesync = rand.nextFloat() * 0.05F; } - @Override - public String getConfigName() { - return "steamturbineIndustrial"; - } - - @Override - public void readIfPresent(JsonObject obj) { - maxPower = IConfigurableMachine.grab(obj, "L:maxPower", maxPower); - inputTankSize = IConfigurableMachine.grab(obj, "I:inputTankSize", inputTankSize); - outputTankSize = IConfigurableMachine.grab(obj, "I:outputTankSize", outputTankSize); - efficiency = IConfigurableMachine.grab(obj, "D:efficiency", efficiency); - } - - @Override - public void writeConfig(JsonWriter writer) throws IOException { - writer.name("L:maxPower").value(maxPower); - writer.name("INFO").value("industrial steam turbine consumes 20% of availible steam per tick"); - writer.name("I:inputTankSize").value(inputTankSize); - writer.name("I:outputTankSize").value(outputTankSize); - writer.name("D:efficiency").value(efficiency); - } - @Override public String getName() { return "container.machineLargeTurbine"; diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntitySteamEngine.java b/src/main/java/com/hbm/tileentity/machine/TileEntitySteamEngine.java index d0297d2f8..f32c6e9ed 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntitySteamEngine.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntitySteamEngine.java @@ -70,7 +70,7 @@ public class TileEntitySteamEngine extends TileEntityLoadedBase implements IEner writer.name("D:efficiency").value(efficiency); } - ByteBuf buf; + protected ByteBuf buf; @Override public void updateEntity() { diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityTurbineBase.java b/src/main/java/com/hbm/tileentity/machine/TileEntityTurbineBase.java new file mode 100644 index 000000000..b516b11b4 --- /dev/null +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityTurbineBase.java @@ -0,0 +1,185 @@ +package com.hbm.tileentity.machine; + +import com.hbm.inventory.fluid.FluidType; +import com.hbm.inventory.fluid.Fluids; +import com.hbm.inventory.fluid.tank.FluidTank; +import com.hbm.inventory.fluid.trait.FT_Coolable; +import com.hbm.inventory.fluid.trait.FT_Coolable.CoolingType; +import com.hbm.tileentity.IBufPacketReceiver; +import com.hbm.tileentity.IFluidCopiable; +import com.hbm.tileentity.TileEntityLoadedBase; +import com.hbm.util.CompatEnergyControl; +import com.hbm.util.fauxpointtwelve.DirPos; + +import api.hbm.energymk2.IEnergyProviderMK2; +import api.hbm.fluidmk2.IFluidStandardTransceiverMK2; +import api.hbm.tile.IInfoProviderEC; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import net.minecraft.nbt.NBTTagCompound; + +public abstract class TileEntityTurbineBase extends TileEntityLoadedBase implements IEnergyProviderMK2, IFluidStandardTransceiverMK2, IInfoProviderEC, IBufPacketReceiver, IFluidCopiable { + + protected ByteBuf buf; + public long powerBuffer; + + public FluidTank[] tanks; + protected double[] info = new double[3]; + public boolean operational = false; + + public abstract double getEfficiency(); + public abstract DirPos[] getConPos(); + public abstract DirPos[] getPowerPos(); + public abstract double consumptionPercent(); + + public void generatePower(long power, int steamConsumed) { + this.powerBuffer += power; + } + + @Override + public void updateEntity() { + + if(!worldObj.isRemote) { + + this.powerBuffer = 0; + this.info = new double[3]; + + if(this.buf != null) this.buf.release(); + this.buf = Unpooled.buffer(); + + this.tanks[0].serialize(buf); + + operational = false; + FluidType in = tanks[0].getTankType(); + boolean valid = false; + if(in.hasTrait(FT_Coolable.class)) { + FT_Coolable trait = in.getTrait(FT_Coolable.class); + double eff = trait.getEfficiency(CoolingType.TURBINE) * getEfficiency(); + if(eff > 0) { + tanks[1].setTankType(trait.coolsTo); + int inputOps = (int) Math.ceil((tanks[0].getFill() * consumptionPercent()) / trait.amountReq); + int outputOps = (tanks[1].getMaxFill() - tanks[1].getFill()) / trait.amountProduced; + int ops = Math.min(inputOps, outputOps); + if(ops > 0) { + tanks[0].setFill(tanks[0].getFill() - ops * trait.amountReq); + tanks[1].setFill(tanks[1].getFill() + ops * trait.amountProduced); + this.generatePower((long) (ops * trait.heatEnergy * eff), tanks[0].getFill() - ops * trait.amountReq); + } + info[0] = ops * trait.amountReq; + info[1] = ops * trait.amountProduced; + info[2] = ops * trait.heatEnergy * eff; + valid = true; + operational = ops > 0; + } + } + + onServerTick(); + + this.tanks[1].serialize(buf); + this.buf.writeLong(this.powerBuffer); + + if(!valid) tanks[1].setTankType(Fluids.NONE); + + for(DirPos pos : this.getPowerPos()) { + this.tryProvide(worldObj, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); + } + + for(DirPos pos : this.getConPos()) { + this.tryProvide(tanks[1], worldObj, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); + this.trySubscribe(tanks[0].getTankType(), worldObj, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); + } + networkPackNT(150); + + } else { + onClientTick(); + } + } + + public void onServerTick() { } + public void onClientTick() { } + + public void onLeverPull() { + + FluidType type = tanks[0].getTankType(); + + if(type == Fluids.STEAM) { + tanks[0].setTankType(Fluids.HOTSTEAM); + tanks[1].setTankType(Fluids.STEAM); + tanks[0].setFill(tanks[0].getFill() / 10); + tanks[1].setFill(0); + } else if(type == Fluids.HOTSTEAM) { + tanks[0].setTankType(Fluids.SUPERHOTSTEAM); + tanks[1].setTankType(Fluids.HOTSTEAM); + tanks[0].setFill(tanks[0].getFill() / 10); + tanks[1].setFill(0); + } else if(type == Fluids.SUPERHOTSTEAM) { + tanks[0].setTankType(Fluids.ULTRAHOTSTEAM); + tanks[1].setTankType(Fluids.SUPERHOTSTEAM); + tanks[0].setFill(tanks[0].getFill() / 10); + tanks[1].setFill(0); + } else { + tanks[0].setTankType(Fluids.STEAM); + tanks[1].setTankType(Fluids.SPENTSTEAM); + tanks[0].setFill(Math.min(tanks[0].getFill() * 1000, tanks[0].getMaxFill())); + tanks[1].setFill(0); + } + + markDirty(); + } + + @Override + public void serialize(ByteBuf buf) { + super.serialize(buf); + buf.writeBytes(this.buf); + } + + @Override + public void deserialize(ByteBuf buf) { + super.deserialize(buf); + this.tanks[0].deserialize(buf); + this.tanks[1].deserialize(buf); + this.powerBuffer = buf.readLong(); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + tanks[0].readFromNBT(nbt, "water"); + tanks[1].readFromNBT(nbt, "steam"); + powerBuffer = nbt.getLong("power"); + } + + @Override + public void writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + tanks[0].writeToNBT(nbt, "water"); + tanks[1].writeToNBT(nbt, "steam"); + nbt.setLong("power", powerBuffer); + } + + @Override public long getPower() { return powerBuffer; } + @Override public long getMaxPower() { return powerBuffer; } + @Override public void setPower(long power) { this.powerBuffer = power; } + + @Override public FluidTank[] getSendingTanks() { return new FluidTank[] {tanks[1]}; } + @Override public FluidTank[] getReceivingTanks() { return new FluidTank[] {tanks[0]}; } + @Override public FluidTank[] getAllTanks() { return tanks; } + + @Override + public void provideExtraInfo(NBTTagCompound data) { + data.setBoolean(CompatEnergyControl.B_ACTIVE, info[1] > 0); + data.setDouble(CompatEnergyControl.D_CONSUMPTION_MB, info[0]); + data.setDouble(CompatEnergyControl.D_OUTPUT_MB, info[1]); + data.setDouble(CompatEnergyControl.D_OUTPUT_HE, info[2]); + } + + @Override public FluidTank getTankToPaste() { return null; } + + @Override + @SideOnly(Side.CLIENT) + public double getMaxRenderDistanceSquared() { + return 65536.0D; + } +} diff --git a/src/main/resources/assets/hbm/models/machines/industrial_turbine.obj b/src/main/resources/assets/hbm/models/machines/industrial_turbine.obj index c09c29df7..a551b8a5f 100644 --- a/src/main/resources/assets/hbm/models/machines/industrial_turbine.obj +++ b/src/main/resources/assets/hbm/models/machines/industrial_turbine.obj @@ -429,7 +429,7 @@ f 64/69/15 88/161/15 78/136/4 f 54/71/14 77/162/14 79/137/13 f 61/25/17 85/163/17 86/138/6 f 58/75/11 82/164/11 83/139/8 -o Gauuge_Gauge +o Gauge v -0.031250 1.531250 3.468750 v -0.031250 1.468750 3.468750 v 0.031250 1.531250 3.468750 diff --git a/src/main/resources/assets/hbm/textures/models/machines/chungus.png b/src/main/resources/assets/hbm/textures/models/machines/chungus.png index 30b90952229a41a2bb91ef8296264cb5d028d838..88a65a58b6b3e513922ff02fc6cefc724924fbe9 100644 GIT binary patch literal 16204 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 literal 16198 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 I$QlRz9~2?_`v3p{ diff --git a/src/main/resources/assets/hbm/textures/models/machines/industrial_turbine.png b/src/main/resources/assets/hbm/textures/models/machines/industrial_turbine.png index e72fef4b2b65a13ee39ddec4122b7d605163d081..2f8060c7dd6e0756977a01b51a78436da17cec6e 100644 GIT binary patch literal 10230 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±^eSj$fY@nJ4u16OOzc9r*$X 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