From 42def514787c6598ecd21addba6ff0646bf63916 Mon Sep 17 00:00:00 2001 From: Timo Ley Date: Sat, 17 Apr 2021 16:07:41 +0200 Subject: [PATCH] Add Force Engine prototype --- .../buildcraft/api/tools/IToolWrench.java | 40 ++ .../cofh/api/energy/IEnergyConnection.java | 8 + .../java/cofh/api/energy/IEnergyProvider.java | 12 + .../java/cofh/api/energy/IEnergyReceiver.java | 12 + .../java/cofh/api/energy/IEnergyStorage.java | 13 + .../java/ley/modding/dartcraft/Config.java | 70 ++- .../java/ley/modding/dartcraft/Dartcraft.java | 5 +- .../dartcraft/api/energy/EngineLiquid.java | 44 ++ .../dartcraft/block/BlockForceEngine.java | 134 +++++ .../dartcraft/block/BlockLiquidForce.java | 121 ++++ .../modding/dartcraft/block/DartBlocks.java | 11 + .../dartcraft/block/FluidLiquidForce.java | 16 + .../client/gui/ContainerForceEngine.java | 103 ++++ .../dartcraft/client/gui/GuiEngine.java | 222 ++++++++ .../dartcraft/client/gui/GuiHandler.java | 16 + .../dartcraft/client/gui/tabs/GuiTab.java | 295 ++++++++++ .../dartcraft/client/gui/tabs/Tab.java | 151 +++++ .../dartcraft/client/gui/tabs/TabVars.java | 23 + .../dartcraft/client/model/ModelEngine.java | 34 ++ .../renderer/block/RenderTileForceEngine.java | 117 ++++ .../renderer/item/RenderItemEngine.java | 23 + .../modding/dartcraft/proxy/ClientProxy.java | 14 +- .../dartcraft/tile/TileEntityForceEngine.java | 532 ++++++++++++++++++ .../ley/modding/dartcraft/util/DartUtils.java | 83 +++ .../dartcraft/util/ForceConsumerUtils.java | 28 + .../dartcraft/util/ForceEngineLiquids.java | 290 ++++++++++ .../modding/dartcraft/util/FortunesUtil.java | 220 ++++++++ .../resources/assets/dartcraft/engineGui.png | Bin 0 -> 23378 bytes .../assets/dartcraft/forceEngine.png | Bin 0 -> 5375 bytes src/main/resources/assets/dartcraft/items.png | Bin 0 -> 18699 bytes .../textures/blocks/liquidForceMoving.png | Bin 0 -> 12733 bytes .../blocks/liquidForceMoving.png.mcmeta | 5 + .../textures/blocks/liquidForceStill.png | Bin 0 -> 14006 bytes .../blocks/liquidForceStill.png.mcmeta | 45 ++ .../assets/dartcraft/textures/blocks/milk.png | Bin 0 -> 8200 bytes .../dartcraft/textures/blocks/milk.png.mcmeta | 42 ++ 36 files changed, 2725 insertions(+), 4 deletions(-) create mode 100644 src/main/java/buildcraft/api/tools/IToolWrench.java create mode 100644 src/main/java/cofh/api/energy/IEnergyConnection.java create mode 100644 src/main/java/cofh/api/energy/IEnergyProvider.java create mode 100644 src/main/java/cofh/api/energy/IEnergyReceiver.java create mode 100644 src/main/java/cofh/api/energy/IEnergyStorage.java create mode 100644 src/main/java/ley/modding/dartcraft/api/energy/EngineLiquid.java create mode 100644 src/main/java/ley/modding/dartcraft/block/BlockForceEngine.java create mode 100644 src/main/java/ley/modding/dartcraft/block/BlockLiquidForce.java create mode 100644 src/main/java/ley/modding/dartcraft/block/FluidLiquidForce.java create mode 100644 src/main/java/ley/modding/dartcraft/client/gui/ContainerForceEngine.java create mode 100644 src/main/java/ley/modding/dartcraft/client/gui/GuiEngine.java create mode 100644 src/main/java/ley/modding/dartcraft/client/gui/tabs/GuiTab.java create mode 100644 src/main/java/ley/modding/dartcraft/client/gui/tabs/Tab.java create mode 100644 src/main/java/ley/modding/dartcraft/client/gui/tabs/TabVars.java create mode 100644 src/main/java/ley/modding/dartcraft/client/model/ModelEngine.java create mode 100644 src/main/java/ley/modding/dartcraft/client/renderer/block/RenderTileForceEngine.java create mode 100644 src/main/java/ley/modding/dartcraft/client/renderer/item/RenderItemEngine.java create mode 100644 src/main/java/ley/modding/dartcraft/tile/TileEntityForceEngine.java create mode 100644 src/main/java/ley/modding/dartcraft/util/DartUtils.java create mode 100644 src/main/java/ley/modding/dartcraft/util/ForceEngineLiquids.java create mode 100644 src/main/java/ley/modding/dartcraft/util/FortunesUtil.java create mode 100644 src/main/resources/assets/dartcraft/engineGui.png create mode 100644 src/main/resources/assets/dartcraft/forceEngine.png create mode 100644 src/main/resources/assets/dartcraft/items.png create mode 100644 src/main/resources/assets/dartcraft/textures/blocks/liquidForceMoving.png create mode 100644 src/main/resources/assets/dartcraft/textures/blocks/liquidForceMoving.png.mcmeta create mode 100644 src/main/resources/assets/dartcraft/textures/blocks/liquidForceStill.png create mode 100644 src/main/resources/assets/dartcraft/textures/blocks/liquidForceStill.png.mcmeta create mode 100644 src/main/resources/assets/dartcraft/textures/blocks/milk.png create mode 100644 src/main/resources/assets/dartcraft/textures/blocks/milk.png.mcmeta diff --git a/src/main/java/buildcraft/api/tools/IToolWrench.java b/src/main/java/buildcraft/api/tools/IToolWrench.java new file mode 100644 index 0000000..2a627e3 --- /dev/null +++ b/src/main/java/buildcraft/api/tools/IToolWrench.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2011-2017, SpaceToad and the BuildCraft Team + * http://www.mod-buildcraft.com + * + * The BuildCraft API is distributed under the terms of the MIT License. + * Please check the contents of the license, which should be located + * as "LICENSE.API" in the BuildCraft source code distribution. + */ +package buildcraft.api.tools; + +import net.minecraft.entity.player.EntityPlayer; + +/*** + * Implement this interface on subclasses of Item to have that item work as a wrench for buildcraft + */ +public interface IToolWrench { + + /*** + * Called to ensure that the wrench can be used. To get the ItemStack that is used, check player.inventory.getCurrentItem() + * + * @param player + * - The player doing the wrenching + * @param x + * ,y,z - The coordinates for the block being wrenched + * + * @return true if wrenching is allowed, false if not + */ + boolean canWrench(EntityPlayer player, int x, int y, int z); + + /*** + * Callback after the wrench has been used. This can be used to decrease durability or for other purposes. To get the ItemStack that was used, check + * player.inventory.getCurrentItem() + * + * @param player + * - The player doing the wrenching + * @param x + * ,y,z - The coordinates of the block being wrenched + */ + void wrenchUsed(EntityPlayer player, int x, int y, int z); +} diff --git a/src/main/java/cofh/api/energy/IEnergyConnection.java b/src/main/java/cofh/api/energy/IEnergyConnection.java new file mode 100644 index 0000000..4c264e6 --- /dev/null +++ b/src/main/java/cofh/api/energy/IEnergyConnection.java @@ -0,0 +1,8 @@ +package cofh.api.energy; + +import net.minecraftforge.common.util.ForgeDirection; + +public interface IEnergyConnection { + + boolean canConnectEnergy(ForgeDirection var1); +} diff --git a/src/main/java/cofh/api/energy/IEnergyProvider.java b/src/main/java/cofh/api/energy/IEnergyProvider.java new file mode 100644 index 0000000..f4d2a6c --- /dev/null +++ b/src/main/java/cofh/api/energy/IEnergyProvider.java @@ -0,0 +1,12 @@ +package cofh.api.energy; + +import net.minecraftforge.common.util.ForgeDirection; + +public interface IEnergyProvider extends IEnergyConnection { + + int extractEnergy(ForgeDirection var1, int var2, boolean var3); + + int getEnergyStored(ForgeDirection var1); + + int getMaxEnergyStored(ForgeDirection var1); +} diff --git a/src/main/java/cofh/api/energy/IEnergyReceiver.java b/src/main/java/cofh/api/energy/IEnergyReceiver.java new file mode 100644 index 0000000..00cacc8 --- /dev/null +++ b/src/main/java/cofh/api/energy/IEnergyReceiver.java @@ -0,0 +1,12 @@ +package cofh.api.energy; + +import net.minecraftforge.common.util.ForgeDirection; + +public interface IEnergyReceiver extends IEnergyConnection { + + int receiveEnergy(ForgeDirection var1, int var2, boolean var3); + + int getEnergyStored(ForgeDirection var1); + + int getMaxEnergyStored(ForgeDirection var1); +} diff --git a/src/main/java/cofh/api/energy/IEnergyStorage.java b/src/main/java/cofh/api/energy/IEnergyStorage.java new file mode 100644 index 0000000..258c304 --- /dev/null +++ b/src/main/java/cofh/api/energy/IEnergyStorage.java @@ -0,0 +1,13 @@ +package cofh.api.energy; + + +public interface IEnergyStorage { + + int receiveEnergy(int var1, boolean var2); + + int extractEnergy(int var1, boolean var2); + + int getEnergyStored(); + + int getMaxEnergyStored(); +} diff --git a/src/main/java/ley/modding/dartcraft/Config.java b/src/main/java/ley/modding/dartcraft/Config.java index b1085eb..5acbbfc 100644 --- a/src/main/java/ley/modding/dartcraft/Config.java +++ b/src/main/java/ley/modding/dartcraft/Config.java @@ -1,5 +1,11 @@ package ley.modding.dartcraft; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.Iterator; + public class Config { public static boolean hardHeat; @@ -14,8 +20,70 @@ public class Config { public static int damageLevel; public static int sturdyLevel; - public static float gemValue; + public static float gemValue = 0.25F; public static int powerOreRenderID; + public static File engineFile; + + + private static void generateDefaultEngineFile() { + try { + FileWriter e = new FileWriter(engineFile); + BufferedWriter buffer = new BufferedWriter(e); + buffer.write("#Place the Forge Liquid name (all lowercase) you wish to add as a fuel or\n"); + buffer.write("#throttle under the appropriate category using the below syntax.\n"); + buffer.write("#The first number is the burn value and the second is burn time.\n"); + buffer.write("#Liquid Force must be added as a fuel or defaults will be asserted.\n"); + Iterator i$ = getDefaultFuels().iterator(); + + while(i$.hasNext()) { + String name = (String)i$.next(); + buffer.write(name); + buffer.write(10); + } + + buffer.close(); + } catch (Exception var4) { + var4.printStackTrace(); + } + + } + + private static ArrayList getDefaultFuels() { + ArrayList defaults = new ArrayList(); + //defaults.add("#Fuels."); + defaults.add("f:liquidforce=4.0;20000"); + defaults.add("f:lava=0.5;20000"); + defaults.add("f:oil=1.5;20000"); + defaults.add("f:fuel=3.0;100000"); + defaults.add("f:bioethanol=2.0;60000"); + //defaults.add("\n#Throttles."); + defaults.add("t:water=2.0;600"); + defaults.add("t:milk=2.5;3000"); + defaults.add("t:ice=4.0;20000"); + defaults.add("t:honey=3.0;10000"); + return defaults; + } + + public static ArrayList getFuels() { + /* ArrayList fuels = new ArrayList(); + + try { + BufferedReader e = new BufferedReader(new FileReader(engineFile)); + String line = null; + + while((line = e.readLine()) != null) { + if(!line.startsWith("#") && !line.startsWith("\n")) { + fuels.add("" + line); + } + } + } catch (Exception var3) { + var3.printStackTrace(); + } + + return fuels;*/ + return getDefaultFuels(); + } + } diff --git a/src/main/java/ley/modding/dartcraft/Dartcraft.java b/src/main/java/ley/modding/dartcraft/Dartcraft.java index 301bfa1..f23d063 100644 --- a/src/main/java/ley/modding/dartcraft/Dartcraft.java +++ b/src/main/java/ley/modding/dartcraft/Dartcraft.java @@ -17,6 +17,8 @@ import ley.modding.dartcraft.item.DartItems; import ley.modding.dartcraft.network.PacketClipButton; import ley.modding.dartcraft.proxy.CommonProxy; import ley.modding.dartcraft.tab.DartcraftTab; +import ley.modding.dartcraft.util.ForceEngineLiquids; +import ley.modding.dartcraft.util.FortunesUtil; import ley.modding.tileralib.api.IRegistry; import net.minecraft.creativetab.CreativeTabs; import net.minecraftforge.common.MinecraftForge; @@ -42,6 +44,7 @@ public class Dartcraft { MinecraftForge.EVENT_BUS.register(new EventHandler()); channel = NetworkRegistry.INSTANCE.newSimpleChannel("Dartcraft"); channel.registerMessage(PacketClipButton.Handler.class, PacketClipButton.class, 0, Side.SERVER); + FortunesUtil.load(); } @Mod.EventHandler @@ -62,7 +65,7 @@ public class Dartcraft { @Mod.EventHandler public void postInit(FMLPostInitializationEvent e) { - + ForceEngineLiquids.load(); } } diff --git a/src/main/java/ley/modding/dartcraft/api/energy/EngineLiquid.java b/src/main/java/ley/modding/dartcraft/api/energy/EngineLiquid.java new file mode 100644 index 0000000..5ac088d --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/api/energy/EngineLiquid.java @@ -0,0 +1,44 @@ +package ley.modding.dartcraft.api.energy; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; + +public class EngineLiquid { + public static final int TYPE_FUEL = 0; + + public static final int TYPE_THROTTLE = 1; + + protected int id; + + protected int burnTime; + + protected int type; + + protected NBTTagCompound comp; + + protected float modifier = 1.0F; + + public EngineLiquid(FluidStack liquid, int type, int burnTime, float modifier) { + this.id = liquid.getFluidID(); + this.comp = liquid.tag; + this.type = type; + this.burnTime = burnTime; + this.modifier = modifier; + } + + public int getType() { + return this.type; + } + + public int getBurnTime() { + return this.burnTime; + } + + public float getModifier() { + return this.modifier; + } + + public FluidStack getLiquid() { + return new FluidStack(this.id, 1000); + } +} diff --git a/src/main/java/ley/modding/dartcraft/block/BlockForceEngine.java b/src/main/java/ley/modding/dartcraft/block/BlockForceEngine.java new file mode 100644 index 0000000..243999b --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/block/BlockForceEngine.java @@ -0,0 +1,134 @@ +package ley.modding.dartcraft.block; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import ley.modding.dartcraft.Dartcraft; +import ley.modding.dartcraft.tile.TileEntityForceEngine; +import ley.modding.dartcraft.util.DartUtils; +import ley.modding.tileralib.api.ITEProvider; +import net.minecraft.block.Block; +import net.minecraft.block.BlockContainer; +import net.minecraft.block.material.Material; +import net.minecraft.client.particle.EffectRenderer; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidContainerRegistry; + +public class BlockForceEngine extends BlockContainer implements ITEProvider { + + public BlockForceEngine() { + super(Material.iron); + setHardness(3.0F); + setResistance(50.0F); + setCreativeTab(Dartcraft.tab); + setBlockName("forceengine"); + } + + public TileEntity createNewTileEntity(World world, int var2) { + return new TileEntityForceEngine(); + } + + public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int par6, float par7, float par8, float par9) { + if(!Dartcraft.proxy.isSimulating(world)) { + return true; + } else { + TileEntity tile = world.getTileEntity(x, y, z); + TileEntityForceEngine engine = null; + if(tile instanceof TileEntityForceEngine) { + engine = (TileEntityForceEngine)tile; + } + + if(engine != null) { + if(DartUtils.isHoldingWrench(player)) { + engine.rotateBlock(); + return true; + } + + if(player.getCurrentEquippedItem() != null && FluidContainerRegistry.getFluidForFilledItem(player.getCurrentEquippedItem()) != null) { + return DartUtils.fillTankWithContainer(engine, player); + } + + if(!player.isSneaking() && !DartUtils.isHoldingWrench(player)) { + player.openGui(Dartcraft.instance, 7, world, x, y, z); + } + } + + return true; + } + } + + public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase living, ItemStack stack) { + TileEntityForceEngine tile = (TileEntityForceEngine)world.getTileEntity(x, y, z); + if(tile != null) { + tile.setFacing(ForgeDirection.UP); + tile.rotateBlock(); + } + + } + + public int getLightValue(IBlockAccess world, int x, int y, int z) { + TileEntity te = world.getTileEntity(x, y, z); + return te instanceof TileEntityForceEngine?((TileEntityForceEngine)te).getLightValue():0; + } + + public int getRenderType() { + return -1; + } + + public boolean isOpaqueCube() { + return false; + } + + public boolean renderAsNormalBlock() { + return false; + } + + public void breakBlock(World world, int x, int y, int z, Block par5, int par6) { + if(Dartcraft.proxy.isSimulating(world)) { + TileEntity tile = world.getTileEntity(x, y, z); + if(tile instanceof TileEntityForceEngine) { + TileEntityForceEngine engine = (TileEntityForceEngine)tile; + + for(int i = 0; i < engine.liquidInventory.getSizeInventory(); ++i) { + ItemStack tempStack = engine.liquidInventory.getStackInSlot(i); + if(tempStack != null) { + DartUtils.dropItem(tempStack, world, x, y, z); + } + } + } + + super.breakBlock(world, x, y, z, par5, par6); + } + } + + @Override + public boolean isSideSolid(IBlockAccess world, int x, int y, int z, ForgeDirection side) { + TileEntity tile = world.getTileEntity(x, y, z); + return tile instanceof TileEntityForceEngine ?((TileEntityForceEngine)tile).facing.getOpposite() == side:false; + } + + @SideOnly(Side.CLIENT) + public boolean addDestroyEffects(World world, int x, int y, int z, int meta, EffectRenderer renderer) { + //FXUtils.makeShiny(world, (double)x, (double)y, (double)z, 2, 16776960, 16, true); + return true; + } + + @SideOnly(Side.CLIENT) + public boolean addHitEffects(World world, MovingObjectPosition target, EffectRenderer renderer) { + if(world != null && target != null) { //TODO FX + //FXUtils.makeShiny(world, (double)target.blockX, (double)target.blockY, (double)target.blockZ, 2, 16776960, 3, true); + } + return true; + } + + @Override + public Class getTEClass() { + return TileEntityForceEngine.class; + } +} diff --git a/src/main/java/ley/modding/dartcraft/block/BlockLiquidForce.java b/src/main/java/ley/modding/dartcraft/block/BlockLiquidForce.java new file mode 100644 index 0000000..79619f6 --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/block/BlockLiquidForce.java @@ -0,0 +1,121 @@ +package ley.modding.dartcraft.block; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import ley.modding.dartcraft.Dartcraft; +import ley.modding.dartcraft.entity.EntityColdChicken; +import ley.modding.dartcraft.entity.EntityColdCow; +import ley.modding.dartcraft.entity.EntityColdPig; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityAgeable; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.passive.EntitySheep; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.util.IIcon; +import net.minecraft.util.Vec3; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.fluids.BlockFluidClassic; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; + +public class BlockLiquidForce extends BlockFluidClassic { + + public IIcon still; + public IIcon flowing; + public IIcon milk; + + public BlockLiquidForce() { + super(FluidRegistry.getFluid("liquidforce"), Material.water); + Fluid liquidForce = FluidRegistry.getFluid("liquidforce"); + if (liquidForce != null) + liquidForce.setBlock(DartBlocks.liquidforce); + setResistance(2000.0F); + setBlockName("liquidforce"); + } + + public int getLightValue(IBlockAccess world, int x, int y, int z) { + return 15; + } + + public void velocityToAddToEntity(World world, int x, int y, int z, Entity entity, Vec3 vec) { + if (entity == null) + return; + try { + double modifier = 0.85D; + entity.motionX *= modifier; + entity.motionY *= modifier; + entity.motionZ *= modifier; + } catch (Exception e) {} + } + + public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity) { + try { + if (entity instanceof EntityLivingBase) { + EntityLivingBase living = (EntityLivingBase)entity; + if (living.isEntityUndead() || living instanceof net.minecraft.entity.monster.EntityBlaze) { + living.addPotionEffect(new PotionEffect(Potion.weakness.getId(), 1, 9, false)); + /*if (Config.baneForce) { + living.attackEntityFrom((DamageSource) PunishDamage.instance, 2.0F); + } else {*/ + living.attackEntityFrom(DamageSource.magic, 2.0F); + //} + } else { + if (living.getAir() < 255) + living.setAir(living.getAir() + 1); + living.heal(0.005F); + living.removePotionEffect(Potion.invisibility.getId()); + living.removePotionEffect(Potion.wither.getId()); + } + if (Dartcraft.proxy.isSimulating(world)) { + float chance = 0.9925F; + if (living instanceof EntityColdCow && living.getRNG().nextFloat() > chance) { + EntityColdCow cow = (EntityColdCow)living; + //cow.shouldRevert = true; + } + if (living instanceof EntityColdChicken && living.getRNG().nextFloat() > chance) { + EntityColdChicken chicken = (EntityColdChicken)living; + //chicken.shouldRevert = true; + } + if (living instanceof EntityColdPig && living.getRNG().nextFloat() > chance) { + EntityColdPig pig = (EntityColdPig)living; + //pig.shouldRevert = true; + } + if (living instanceof EntitySheep && living.getRNG().nextFloat() > chance) { + EntitySheep sheep = (EntitySheep)living; + sheep.eatGrassBonus(); + } + if (living instanceof EntityAgeable && !(living instanceof net.minecraft.entity.passive.EntityHorse)) { + EntityAgeable animal = (EntityAgeable)living; + if (animal.getGrowingAge() < 0) + animal.setGrowingAge((animal.getGrowingAge() < -20) ? (animal.getGrowingAge() + 20) : 0); + } + } + } + } catch (Exception e) {} + } + + public Fluid getFluid() { + return FluidRegistry.getFluid("liquidforce"); + } + + @SideOnly(Side.CLIENT) + public void registerBlockIcons(IIconRegister reggie) { + still = reggie.registerIcon("dartcraft:liquidForceStill"); + flowing = reggie.registerIcon("dartcraft:liquidForceMoving"); + Fluid liquidForce = FluidRegistry.getFluid("liquidforce"); + if (liquidForce != null) + liquidForce.setIcons(still, flowing); + blockIcon = still; + milk = reggie.registerIcon("dartcraft:milk"); + Fluid fmilk = FluidRegistry.getFluid("milk"); + if (fmilk != null && milk != null) { + fmilk.setIcons(milk, milk); + } + } +} + diff --git a/src/main/java/ley/modding/dartcraft/block/DartBlocks.java b/src/main/java/ley/modding/dartcraft/block/DartBlocks.java index 1bf6e7b..520aa8c 100644 --- a/src/main/java/ley/modding/dartcraft/block/DartBlocks.java +++ b/src/main/java/ley/modding/dartcraft/block/DartBlocks.java @@ -2,17 +2,28 @@ package ley.modding.dartcraft.block; import ley.modding.tileralib.api.IRegistry; import net.minecraft.block.Block; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; public class DartBlocks { public static Block powerore; public static Block forcesapling; public static Block forcelog; public static Block forceleaves; + public static Block engine; + public static Block liquidforce; public static void register(IRegistry reg) { + FluidRegistry.registerFluid(new FluidLiquidForce()); + if (!FluidRegistry.isFluidRegistered("milk")) { + Fluid milk = new Fluid("milk"); + FluidRegistry.registerFluid(milk); + } + DartBlocks.liquidforce = reg.registerBlock(new BlockLiquidForce()); DartBlocks.forcesapling = reg.registerBlock(new BlockForceSapling()); DartBlocks.powerore = reg.registerBlock(new BlockPowerOre()); DartBlocks.forcelog = reg.registerBlock(new BlockForceLog()); DartBlocks.forceleaves = reg.registerBlock(new BlockForceLeaves()); + DartBlocks.engine = reg.registerBlock(new BlockForceEngine()); } } diff --git a/src/main/java/ley/modding/dartcraft/block/FluidLiquidForce.java b/src/main/java/ley/modding/dartcraft/block/FluidLiquidForce.java new file mode 100644 index 0000000..1cfa192 --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/block/FluidLiquidForce.java @@ -0,0 +1,16 @@ +package ley.modding.dartcraft.block; + +import net.minecraftforge.fluids.Fluid; + +public class FluidLiquidForce extends Fluid { + public FluidLiquidForce() { + super("liquidForce"); + this.luminosity = 15; + this.viscosity = 6000; + this.density = 200; + } + + public String getLocalizedName() { + return "Liquid Force"; + } +} diff --git a/src/main/java/ley/modding/dartcraft/client/gui/ContainerForceEngine.java b/src/main/java/ley/modding/dartcraft/client/gui/ContainerForceEngine.java new file mode 100644 index 0000000..93bf4ea --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/client/gui/ContainerForceEngine.java @@ -0,0 +1,103 @@ +package ley.modding.dartcraft.client.gui; + +import ley.modding.dartcraft.item.DartItems; +import ley.modding.dartcraft.tile.TileEntityForceEngine; +import ley.modding.dartcraft.util.ForceEngineLiquids; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.ICrafting; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidContainerRegistry; + +public class ContainerForceEngine extends Container { + public TileEntityForceEngine engine; + + public IInventory playerInv; + + public EntityPlayer user; + + public ContainerForceEngine(EntityPlayer player, TileEntityForceEngine engine) { + this.user = player; + this.engine = engine; + this.playerInv = (IInventory)player.inventory; + addSlotToContainer(new FuelSlot((IInventory)engine.liquidInventory, 0, 38, 33)); + addSlotToContainer(new ThrottleSlot((IInventory)engine.liquidInventory, 1, 122, 33)); + int i; + for (i = 0; i < 3; i++) { + for (int j = 0; j < 9; j++) + addSlotToContainer(new Slot(this.playerInv, i * 9 + j + 9, 8 + 18 * j, 79 + 18 * i)); + } + for (i = 0; i < 9; i++) + addSlotToContainer(new Slot(this.playerInv, i, 8 + 18 * i, 137)); + } + + public void detectAndSendChanges() { + super.detectAndSendChanges(); + for (int i = 0; i < crafters.size(); i++) + this.engine.sendGuiNetworkData(this, (ICrafting) crafters.get(i)); + } + + public void updateProgressBar(int i, int j) { + this.engine.receiveGuiNetworkData(i, j); + } + + public ItemStack transferStackInSlot(EntityPlayer player, int index) { + ItemStack returnStack = null; + Slot slot = (Slot) inventorySlots.get(index); + if (slot != null && slot.getHasStack()) { + ItemStack stack = slot.getStack(); + returnStack = stack.copy(); + if (index >= 0 && index < 2) + if (!mergeItemStack(stack, 2, 38, true)) + return null; + if (index >= 2) + if (ForceEngineLiquids.isFuel(FluidContainerRegistry.getFluidForFilledItem(stack)) || stack.getItem() == DartItems.forcegem) { + if (!mergeItemStack(stack, 0, 1, false)) + return null; + } else if (ForceEngineLiquids.isThrottle(FluidContainerRegistry.getFluidForFilledItem(stack)) && + !mergeItemStack(stack, 1, 2, false)) { + return null; + } + if (stack.stackSize == 0) { + slot.putStack((ItemStack)null); + } else { + slot.onSlotChanged(); + } + if (stack.stackSize == returnStack.stackSize) + return null; + slot.onPickupFromSlot(player, stack); + } + return returnStack; + } + + protected void retrySlotClick(int par1, int par2, boolean par3, EntityPlayer par4EntityPlayer) {} + + public boolean canInteractWith(EntityPlayer player) { + return true; + } + + private class FuelSlot extends Slot { + public FuelSlot(IInventory par1iInventory, int par2, int par3, int par4) { + super(par1iInventory, par2, par3, par4); + } + + public boolean isItemValid(ItemStack stack) { + if (stack.getItem() == DartItems.forcegem) + return true; + return ForceEngineLiquids.isFuel(FluidContainerRegistry.getFluidForFilledItem(stack)); + } + } + + private class ThrottleSlot extends Slot { + public ThrottleSlot(IInventory par1iInventory, int par2, int par3, int par4) { + super(par1iInventory, par2, par3, par4); + } + + public boolean isItemValid(ItemStack stack) { + return ForceEngineLiquids.isThrottle(FluidContainerRegistry.getFluidForFilledItem(stack)); + } + } +} + diff --git a/src/main/java/ley/modding/dartcraft/client/gui/GuiEngine.java b/src/main/java/ley/modding/dartcraft/client/gui/GuiEngine.java new file mode 100644 index 0000000..6b77cbd --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/client/gui/GuiEngine.java @@ -0,0 +1,222 @@ +package ley.modding.dartcraft.client.gui; + +import cpw.mods.fml.common.Loader; +import ley.modding.dartcraft.Dartcraft; +import ley.modding.dartcraft.api.energy.EngineLiquid; +import ley.modding.dartcraft.client.gui.tabs.GuiTab; +import ley.modding.dartcraft.client.gui.tabs.Tab; +import ley.modding.dartcraft.tile.TileEntityForceEngine; +import ley.modding.dartcraft.util.ForceEngineLiquids; +import ley.modding.dartcraft.util.FortunesUtil; +import net.minecraft.client.gui.Gui; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + + +public class GuiEngine extends GuiTab { + private TileEntityForceEngine engine; + + private ContainerForceEngine container; + + private Rectangle fuelBounds; + + private Rectangle throttleBounds; + + private Rectangle energyBounds; + + private Rectangle throttleMeterBounds; + + public GuiEngine(ContainerForceEngine container) { + super(container); + this.engine = container.engine; + this.container = container; + this.xSize = 176; + this.ySize = 161; + addTab(new EnergyTab(this)); + addTab(new InfoTab(this)); + } + + public void initGui() { + super.initGui(); + this.fuelBounds = new Rectangle(this.guiLeft + 66, this.guiTop + 11, 16, 58); + this.throttleBounds = new Rectangle(this.guiLeft + 94, this.guiTop + 11, 16, 58); + } + + public List handleItemTooltip(ItemStack stack, int x, int y, List tooltip) { + Point pointerLoc = new Point(x, y); + if (this.fuelBounds.contains(pointerLoc)) + try { + tooltip.add("" + this.engine.fuelTank.getFluid().getFluid().getLocalizedName() + " (" + (this.engine.fuelTank.getFluid()).amount + ")"); + } catch (Exception e) { + tooltip.add("Empty"); + } + if (this.throttleBounds.contains(pointerLoc)) + try { + tooltip.add("" + (this.engine.throttleTank.getInfo()).fluid.getFluid().getName() + " (" + (this.engine.throttleTank.getFluid()).amount + ")"); + } catch (Exception e) { + tooltip.add("Empty"); + } + return tooltip; + } + + @Override + protected void drawGuiContainerBackgroundLayer(float par1, int par2, int par3) { + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + Dartcraft.proxy.bindTexture("engineGui.png"); + int posX = (this.width - this.xSize) / 2; + int posY = (this.height - this.ySize) / 2; + drawTexturedModalRect(posX, posY, 0, 0, this.xSize, this.ySize); + if (this.engine.fuelTank.getFluid() != null && (this.engine.fuelTank.getFluid()).amount > 0) + displayGauge(this.fuelBounds.x, this.fuelBounds.y, this.engine.fuelTank.getFluid()); + if (this.engine.throttleTank.getFluid() != null && (this.engine.throttleTank.getFluid()).amount > 0) + displayGauge(this.throttleBounds.x, this.throttleBounds.y, this.engine.throttleTank.getFluid()); + } + + private void displayGauge(int x, int y, FluidStack liquid) { + int tempx; + if (liquid == null) + return; + int start = 0; + int squaled = (int)(58.0F * liquid.amount / 10000.0F); + Dartcraft.proxy.bindTexture("textures/atlas/blocks.png"); + do { + tempx = 0; + if (squaled > 16) { + tempx = 16; + squaled -= 16; + } else { + tempx = squaled; + squaled = 0; + } + IIcon icon = liquid.getFluid().getStillIcon(); + if (icon == null) + icon = FluidRegistry.LAVA.getStillIcon(); + drawTexturedModelRectFromIcon(x, y + 58 - tempx - start, icon, 16, 16 - 16 - tempx); + start += 16; + } while (tempx != 0 && squaled != 0); + Dartcraft.proxy.bindTexture("engineGui.png"); + drawTexturedModalRect(x, y, 176, 0, 16, 58); + } + + protected void drawTooltips() {} + + private class EnergyTab extends Tab { + public EnergyTab(Gui gui) { + super(gui); + this.leftSide = false; + this.overlayColor = 13914449; + this.maxHeight = 48; + this.maxWidth = 90; + } + + public void draw(int x, int y) { + drawBackground(x, y); + drawIcon("items.png", 49, x + 2, y + 2); + if (!isFullyOpened()) + return; + float output = GuiEngine.this.engine.getEnergyPerProcess(); + float throttle = 0.0F; + if (GuiEngine.this.engine.throttleTank.getFluid() != null) { + EngineLiquid throttleLiquid = ForceEngineLiquids.getEngineLiquid(GuiEngine.this.engine.throttleTank.getFluid()); + if (throttleLiquid != null) + throttle = throttleLiquid.getModifier(); + } + if (!GuiEngine.this.engine.isActive) + output = throttle = 0.0F; + int subColor = 15000804; + Tab.tabFontRenderer.drawStringWithShadow("Output", x + 22, y + 6, 16777215); + Tab.tabFontRenderer.drawStringWithShadow("MJ/t:", x + 8, y + 20, 16777215); + if (output > 0.0F) { + Tab.tabFontRenderer.drawStringWithShadow("" + GuiEngine.this.engine.getEnergyPerProcess(), x + 36, y + 20, subColor); + } else { + Tab.tabFontRenderer.drawStringWithShadow("None", x + 36, y + 20, subColor); + } + Tab.tabFontRenderer.drawStringWithShadow("Throttle:", x + 8, y + 30, 16777215); + if (throttle > 0.0F) { + Tab.tabFontRenderer.drawStringWithShadow("" + throttle, x + 55, y + 30, subColor); + } else { + Tab.tabFontRenderer.drawStringWithShadow("None", x + 55, y + 30, subColor); + } + } + + public String getTooltip() { + return null; + } + } + + private class InfoTab extends Tab { + public ArrayList infoStrings = new ArrayList(); + + private String currentInfo; + + private int index; + + public InfoTab(Gui gui) { + super(gui); + this.leftSide = false; + this.overlayColor = 1217260; + this.maxHeight = 100; + this.maxWidth = 120; + initializeItems(); + this.currentInfo = getRandomItem(); + this.index = -1; + } + + private void initializeItems() { + this.infoStrings.add("The Force Engine can be throttled with a few liquids, most notably water."); + this.infoStrings.add("The Force Engine's output is determined by the base output of the Fuel multiplied by the Throttle's value."); + this.infoStrings.add("The Force Engine will never explode or die of loneliness."); + this.infoStrings.add("The Force Engine requires a redstone signal to run."); + this.infoStrings.add("You can right-click the Force Engine with a valid liquid container to add liquid quickly."); + if (Loader.isModLoaded("BuildCraft|Energy")) { + this.infoStrings.add("A wide variety of fuels are usable inside the Force Engine. While Liquid Force is the most effective, BuildCraft Fuel or even lava is also usable."); + this.infoStrings.add("Using Fuel or Lava in the Force Engine will yield the same output as the Combustion Engine if water is used as a throttle."); + } else { + this.infoStrings.add("Lava is also a valid Force Engine Fuel, although not as effective as Liquid Force."); + } + if (Loader.isModLoaded("Forestry")) { + this.infoStrings.add("Liquid Force may also be obtained by squeezing Force Logs."); + this.infoStrings.add("Milk is also an effective throttle."); + this.infoStrings.add("Did someone say Glacial bees?"); + } + } + + public void toggleOpen() { + super.toggleOpen(); + if (isOpen()) { + this.index++; + if (this.index > this.infoStrings.size()) + this.index = 0; + try { + this.currentInfo = this.infoStrings.get(this.index); + } catch (Exception e) { + this.currentInfo = getRandomItem(); + } + } + } + + public void draw(int x, int y) { + drawBackground(x, y); + drawIcon("items.png", 0, x + 2, y + 2); + if (!isFullyOpened()) + return; + Tab.tabFontRenderer.drawStringWithShadow("Information", x + 22, y + 6, 16777215); + Tab.tabFontRenderer.drawSplitString(this.currentInfo, x + 8, y + 20, this.maxWidth - 14, 0); + } + + private String getRandomItem() { + return FortunesUtil.getFortune(); + } + + public String getTooltip() { + return null; + } + } +} diff --git a/src/main/java/ley/modding/dartcraft/client/gui/GuiHandler.java b/src/main/java/ley/modding/dartcraft/client/gui/GuiHandler.java index 7f5dc19..580bfff 100644 --- a/src/main/java/ley/modding/dartcraft/client/gui/GuiHandler.java +++ b/src/main/java/ley/modding/dartcraft/client/gui/GuiHandler.java @@ -2,12 +2,14 @@ package ley.modding.dartcraft.client.gui; import cpw.mods.fml.common.network.IGuiHandler; import ley.modding.dartcraft.item.ItemClipboard; +import ley.modding.dartcraft.tile.TileEntityForceEngine; import ley.modding.dartcraft.util.EntityUtils; import ley.modding.dartcraft.util.ItemCraftingInventory; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; public class GuiHandler implements IGuiHandler { @@ -21,6 +23,13 @@ public class GuiHandler implements IGuiHandler { if (clipStack != null) return new ContainerClipboard(player, new ItemCraftingInventory(9, clipStack)); break; + case 7: + TileEntity te2 = world.getTileEntity(x, y, z); + if (te2 != null && te2 instanceof TileEntityForceEngine) { + TileEntityForceEngine engine = (TileEntityForceEngine)te2; + return new ContainerForceEngine(player, engine); + } + break; } return null; } @@ -34,6 +43,13 @@ public class GuiHandler implements IGuiHandler { if (clipStack != null) return new GuiClipboard(new ContainerClipboard(player, new ItemCraftingInventory(9, clipStack))); break; + case 7: + TileEntity te2 = world.getTileEntity(x, y, z); + if (te2 instanceof TileEntityForceEngine) { + TileEntityForceEngine engine = (TileEntityForceEngine)te2; + return new GuiEngine(new ContainerForceEngine(player, engine)); + } + break; } return null; } diff --git a/src/main/java/ley/modding/dartcraft/client/gui/tabs/GuiTab.java b/src/main/java/ley/modding/dartcraft/client/gui/tabs/GuiTab.java new file mode 100644 index 0000000..9b94f38 --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/client/gui/tabs/GuiTab.java @@ -0,0 +1,295 @@ +package ley.modding.dartcraft.client.gui.tabs; + +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Container; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; + +public abstract class GuiTab extends GuiContainer { + protected enum SlotColor { + BLUE, RED, YELLOW, ORANGE, GREEN, PURPLE; + } + + protected enum SlotType { + //SINGLE, OUTPUT, DOUBLEOUTPUT; + TOP, BOTTOM, FULL + } + + protected enum SlotRender { + TOP, BOTTOM, FULL; + } + + protected static int SCALE_ENERGY = 42; + + protected static int SCALE_LIQUID = 60; + + protected static int SCALE_PROGRESS = 24; + + protected static int SCALE_SPEED = 16; + + protected ArrayList tabListLeft = new ArrayList(); + + protected ArrayList tabListRight = new ArrayList(); + + protected int mouseX = 0; + + protected int mouseY = 0; + + public static boolean enableGuiBorders; + + public static boolean enableInfoTabs; + + public static boolean enableTutorialTabs; + + public GuiTab(Container container) { + super(container); + } + + protected void func_74189_g(int i, int j) { + GL11.glDisable(2896); + GL11.glDisable(2929); + drawTabs(this.mouseX, this.mouseY); + drawTooltips(); + GL11.glEnable(2896); + GL11.glEnable(2929); + } + + protected abstract void drawTooltips(); + + protected void drawColoredSlot(int x, int y, SlotColor color, SlotType type, SlotRender render) { + if (enableGuiBorders) { + drawColoredSlotWithBorder(x, y, color, type, render); + } else { + drawColoredSlotNoBorder(x, y, color, type, render); + } + } + + protected void drawColoredSlotNoBorder(int x, int y, SlotColor color, SlotType type, SlotRender render) { + int sizeX = 0; + int sizeY = 0; + int offsetX = color.ordinal() / 3 * 128; + int offsetY = color.ordinal() % 3 * 32; + switch (type) { + case TOP: + sizeX = 16; + sizeY = 16; + offsetX += 8; + offsetY += 8; + break; + case BOTTOM: + sizeX = 24; + sizeY = 24; + offsetX += 36; + offsetY += 4; + break; + case FULL: + sizeX = 42; + sizeY = 24; + offsetX += 75; + offsetY += 4; + break; + } + switch (render) { + case TOP: + sizeY /= 2; + break; + case BOTTOM: + sizeY /= 2; + y += sizeY; + offsetY += sizeY; + break; + } + drawTexturedModalRect(x, y, offsetX, offsetY, sizeX, sizeY); + } + + protected void drawColoredSlotWithBorder(int x, int y, SlotColor color, SlotType type, SlotRender render) { + int sizeX = 32; + int sizeY = 32; + int offsetX = color.ordinal() / 3 * 128; + int offsetY = color.ordinal() % 3 * 32; + offsetX += type.ordinal() * 32; + if (type.ordinal() == 2) + sizeX = 64; + switch (type) { + case TOP: + x -= 8; + y -= 8; + break; + case BOTTOM: + x -= 4; + y -= 4; + break; + case FULL: + x -= 11; + y -= 4; + break; + } + switch (render) { + case TOP: + sizeY /= 2; + break; + case BOTTOM: + sizeY /= 2; + y += sizeY; + offsetY += sizeY; + break; + } + drawTexturedModalRect(x, y, offsetX, offsetY, sizeX, sizeY); + } + + protected void drawColoredLiquidSlot(int x, int y, SlotColor color) { + if (enableGuiBorders) { + drawColoredLiquidSlotWithBorder(x, y, color); + } else { + drawColoredLiquidSlotNoBorder(x, y, color); + } + } + + protected void drawColoredLiquidSlotNoBorder(int x, int y, SlotColor color) { + int sizeX = 16; + int sizeY = 60; + int offsetX = color.ordinal() * 32; + int offsetY = 96; + drawTexturedModalRect(x, y, offsetX + 8, offsetY + 2, sizeX, sizeY); + } + + protected void drawColoredLiquidSlotWithBorder(int x, int y, SlotColor color) { + int sizeX = 32; + int sizeY = 64; + int offsetX = color.ordinal() * 32; + int offsetY = 96; + drawTexturedModalRect(x - 8, y - 2, offsetX, offsetY, sizeX, sizeY); + } + + protected void drawLiquid(int j, int k, int liquidId, NBTTagCompound comp, int width, int height) { + int liquidImgIndex = 0; + try { + FluidStack tempStack = new FluidStack(liquidId, 0, comp); + liquidImgIndex = tempStack.getFluid().getSpriteNumber(); + } catch (Exception e) { + return; + } + int imgLine = liquidImgIndex / 16; + int imgColumn = liquidImgIndex - imgLine * 16; + int x = 0; + int y = 0; + int drawHeight = 0; + int drawWidth = 0; + for (x = 0; x < width; x += 16) { + for (y = 0; y < height; y += 16) { + drawWidth = Math.min(width - x, 16); + drawHeight = Math.min(height - y, 16); + drawTexturedModalRect(j + x, k + y, imgColumn * 16, imgLine * 16, drawWidth, drawHeight); + } + } + } + + protected void drawTooltip(String tooltip) { + drawCreativeTabHoveringText(tooltip, this.mouseX, this.mouseY); + } + + protected int getCenteredOffset(String string) { + return getCenteredOffset(string, this.xSize); + } + + protected int getCenteredOffset(String string, int xWidth) { + return (xWidth - fontRendererObj.getStringWidth(string)) / 2; + } + + protected void mouseClicked(int x, int y, int mouseButton) { + super.mouseClicked(x, y, mouseButton); + Tab tab = getTabAtPosition(this.mouseX, this.mouseY); + if (tab != null && !tab.handleMouseClicked(this.mouseX, this.mouseY, mouseButton)) { + if (tab.leftSide) { + for (Tab other : this.tabListLeft) { + if (other != tab && other.isOpen()) + other.toggleOpen(); + } + } else { + for (Tab other : this.tabListRight) { + if (other != tab && other.isOpen()) + other.toggleOpen(); + } + } + tab.toggleOpen(); + } + } + + public void handleMouseInput() { + int x = Mouse.getEventX() * this.width / this.mc.displayWidth; + int y = this.height- Mouse.getEventY() * this.height / this.mc.displayHeight - 1; + this.mouseX = x - (this.width - this.xSize) / 2; + this.mouseY = y - (this.height - this.ySize) / 2; + super.handleMouseInput(); + } + + public void addTab(Tab tab) { + if (tab.leftSide) { + this.tabListLeft.add(tab); + if (TabVars.getOpenedLeftTab() != null && tab.getClass().equals(TabVars.getOpenedLeftTab())) + tab.setFullyOpen(); + } else { + this.tabListRight.add(tab); + if (TabVars.getOpenedRightTab() != null && tab.getClass().equals(TabVars.getOpenedRightTab())) + tab.setFullyOpen(); + } + } + + protected void drawTabs(int mX, int mY) { + int yPosRight = 4; + int yPosLeft = 4; + for (Tab tab1 : this.tabListLeft) { + tab1.update(); + if (!tab1.isVisible()) + continue; + tab1.draw(0, yPosLeft); + yPosLeft += tab1.getHeight(); + } + for (Tab tab1 : this.tabListRight) { + tab1.update(); + if (!tab1.isVisible()) + continue; + tab1.draw(this.xSize, yPosRight); + yPosRight += tab1.getHeight(); + } + Tab tab = getTabAtPosition(mX, mY); + if (tab != null) { + String tooltip = tab.getTooltip(); + if (tooltip != null) + drawTooltip(tooltip); + } + } + + protected Tab getTabAtPosition(int mX, int mY) { + int xShift = 0; + int yShift = 4; + int i; + for (i = 0; i < this.tabListLeft.size(); i++) { + Tab tab = this.tabListLeft.get(i); + if (tab.isVisible()) { + tab.currentShiftX = xShift; + tab.currentShiftY = yShift; + if (tab.intersectsWith(mX, mY, xShift, yShift)) + return tab; + yShift += tab.getHeight(); + } + } + xShift = this.xSize; + yShift = 4; + for (i = 0; i < this.tabListRight.size(); i++) { + Tab tab = this.tabListRight.get(i); + if (tab.isVisible()) { + tab.currentShiftX = xShift; + tab.currentShiftY = yShift; + if (tab.intersectsWith(mX, mY, xShift, yShift)) + return tab; + yShift += tab.getHeight(); + } + } + return null; + } +} diff --git a/src/main/java/ley/modding/dartcraft/client/gui/tabs/Tab.java b/src/main/java/ley/modding/dartcraft/client/gui/tabs/Tab.java new file mode 100644 index 0000000..5143b2d --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/client/gui/tabs/Tab.java @@ -0,0 +1,151 @@ +package ley.modding.dartcraft.client.gui.tabs; + +import cpw.mods.fml.client.FMLClientHandler; +import ley.modding.dartcraft.Dartcraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import org.lwjgl.opengl.GL11; + +public abstract class Tab { + protected static FontRenderer tabFontRenderer = (FMLClientHandler.instance().getClient()).fontRenderer; + + private boolean open; + + protected Gui myGui; + + public boolean leftSide; + + protected int overlayColor = 16777215; + + public int currentShiftX = 0; + + public int currentShiftY = 0; + + protected int limitWidth = 128; + + public int maxWidth = 124; + + protected int minWidth = 22; + + protected int currentWidth = this.minWidth; + + public int maxHeight = 22; + + protected int minHeight = 22; + + protected int currentHeight = this.minHeight; + + public Tab(Gui gui) { + this.myGui = gui; + } + + public abstract void draw(int paramInt1, int paramInt2); + + protected void drawBackground(int x, int y) { + float colorR = (this.overlayColor >> 16 & 0xFF) / 255.0F; + float colorG = (this.overlayColor >> 8 & 0xFF) / 255.0F; + float colorB = (this.overlayColor & 0xFF) / 255.0F; + GL11.glColor4f(colorR, colorG, colorB, 1.0F); + if (this.leftSide) { + Dartcraft.proxy.bindTexture("tab_left.png"); + this.myGui.drawTexturedModalRect(x - this.currentWidth, y + 4, 0, 256 - this.currentHeight + 4, 4, this.currentHeight - 4); + this.myGui.drawTexturedModalRect(x - this.currentWidth + 4, y, 256 - this.currentWidth + 4, 0, this.currentWidth - 4, 4); + this.myGui.drawTexturedModalRect(x - this.currentWidth, y, 0, 0, 4, 4); + this.myGui.drawTexturedModalRect(x - this.currentWidth + 4, y + 4, 256 - this.currentWidth + 4, 256 - this.currentHeight + 4, this.currentWidth - 4, this.currentHeight - 4); + } else { + Dartcraft.proxy.bindTexture("tab_right.png"); + this.myGui.drawTexturedModalRect(x, y, 0, 256 - this.currentHeight, 4, this.currentHeight); + this.myGui.drawTexturedModalRect(x + 4, y, 256 - this.currentWidth + 4, 0, this.currentWidth - 4, 4); + this.myGui.drawTexturedModalRect(x, y, 0, 0, 4, 4); + this.myGui.drawTexturedModalRect(x + 4, y + 4, 256 - this.currentWidth + 4, 256 - this.currentHeight + 4, this.currentWidth - 4, this.currentHeight - 4); + } + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + } + + protected void drawIcon(String texture, int iconIndex, int x, int y) { + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + Dartcraft.proxy.bindTexture(texture); + int textureRow = iconIndex >> 4; + int textureColumn = iconIndex - 16 * textureRow; + this.myGui.drawTexturedModalRect(x, y, 16 * textureColumn, 16 * textureRow, 16, 16); + } + + public int getHeight() { + return this.currentHeight; + } + + public abstract String getTooltip(); + + public boolean handleMouseClicked(int x, int y, int mouseButton) { + return false; + } + + public boolean intersectsWith(int mouseX, int mouseY, int shiftX, int shiftY) { + if (this.leftSide) { + if (mouseX <= shiftX && mouseX >= shiftX - this.currentWidth && mouseY >= shiftY && mouseY <= shiftY + this.currentHeight) + return true; + } else if (mouseX >= shiftX && mouseX <= shiftX + this.currentWidth && mouseY >= shiftY && mouseY <= shiftY + this.currentHeight) { + return true; + } + return false; + } + + protected boolean isFullyOpened() { + return (this.currentWidth >= this.maxWidth); + } + + public boolean isOpen() { + return this.open; + } + + public boolean isVisible() { + return true; + } + + public void setFullyOpen() { + this.open = true; + this.currentWidth = this.maxWidth; + this.currentHeight = this.maxHeight; + } + + public void toggleOpen() { + if (this.open) { + this.open = false; + if (this.leftSide) { + TabVars.setOpenedLeftTab(null); + } else { + TabVars.setOpenedRightTab(null); + } + } else { + this.open = true; + if (this.leftSide) { + TabVars.setOpenedLeftTab(getClass()); + } else { + TabVars.setOpenedRightTab(getClass()); + } + } + } + + public void update() { + if (this.open && this.currentWidth < this.maxWidth) { + this.currentWidth += 8; + } else if (!this.open && this.currentWidth > this.minWidth) { + this.currentWidth -= 8; + } + if (this.currentWidth > this.maxWidth) { + this.currentWidth = this.maxWidth; + } else if (this.currentWidth < this.minWidth) { + this.currentWidth = this.minWidth; + } + if (this.open && this.currentHeight < this.maxHeight) { + this.currentHeight += 8; + } else if (!this.open && this.currentHeight > this.minHeight) { + this.currentHeight -= 8; + } + if (this.currentHeight > this.maxHeight) { + this.currentHeight = this.maxHeight; + } else if (this.currentHeight < this.minHeight) { + this.currentHeight = this.minHeight; + } + } +} diff --git a/src/main/java/ley/modding/dartcraft/client/gui/tabs/TabVars.java b/src/main/java/ley/modding/dartcraft/client/gui/tabs/TabVars.java new file mode 100644 index 0000000..7be7d2b --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/client/gui/tabs/TabVars.java @@ -0,0 +1,23 @@ +package ley.modding.dartcraft.client.gui.tabs; + +public class TabVars { + private static Class openedLeftTab; + + private static Class openedRightTab; + + public static Class getOpenedLeftTab() { + return openedLeftTab; + } + + public static Class getOpenedRightTab() { + return openedRightTab; + } + + public static void setOpenedLeftTab(Class tabClass) { + openedLeftTab = tabClass; + } + + public static void setOpenedRightTab(Class tabClass) { + openedRightTab = tabClass; + } +} diff --git a/src/main/java/ley/modding/dartcraft/client/model/ModelEngine.java b/src/main/java/ley/modding/dartcraft/client/model/ModelEngine.java new file mode 100644 index 0000000..94320dd --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/client/model/ModelEngine.java @@ -0,0 +1,34 @@ +package ley.modding.dartcraft.client.model; + +import net.minecraft.client.renderer.entity.RenderItem; + +public class ModelEngine { + public static float[][] angleBaseYNeg = new float[6][3]; + + public static float[][] angleBaseYPos = new float[6][3]; + + public static float[][] angleBaseXPos = new float[6][3]; + + public static final float factor = 0.0625F; + + public static final RenderItem itemRenderer = new RenderItem(); + + static { + float pi = 3.141593F; + angleBaseYNeg[0][2] = pi; + angleBaseYNeg[2][0] = -pi / 2.0F; + angleBaseYNeg[3][0] = pi / 2.0F; + angleBaseYNeg[4][2] = pi / 2.0F; + angleBaseYNeg[5][2] = -pi / 2.0F; + angleBaseYPos[1][2] = pi; + angleBaseYPos[2][0] = pi / 2.0F; + angleBaseYPos[3][0] = -pi / 2.0F; + angleBaseYPos[4][2] = -pi / 2.0F; + angleBaseYPos[5][2] = pi / 2.0F; + angleBaseXPos[0][0] = -pi / 2.0F; + angleBaseXPos[1][0] = pi / 2.0F; + angleBaseXPos[2][1] = pi; + angleBaseXPos[4][1] = -pi / 2.0F; + angleBaseXPos[5][1] = pi / 2.0F; + } +} diff --git a/src/main/java/ley/modding/dartcraft/client/renderer/block/RenderTileForceEngine.java b/src/main/java/ley/modding/dartcraft/client/renderer/block/RenderTileForceEngine.java new file mode 100644 index 0000000..64106b4 --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/client/renderer/block/RenderTileForceEngine.java @@ -0,0 +1,117 @@ +package ley.modding.dartcraft.client.renderer.block; + +import ley.modding.dartcraft.Dartcraft; +import ley.modding.dartcraft.client.model.ModelEngine; +import ley.modding.dartcraft.tile.TileEntityForceEngine; +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelRenderer; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.tileentity.TileEntity; +import org.lwjgl.opengl.GL11; + +public class RenderTileForceEngine extends TileEntitySpecialRenderer { + private static ModelRenderer base; + + static ModelBase model = new ModelBase() { + + }; + + static ModelRenderer piston; + + static ModelRenderer extension; + + static ModelRenderer[] trunk = new ModelRenderer[2]; + + static double[][] translate = new double[6][3]; + + public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float f) { + TileEntityForceEngine engine; + if (tile instanceof TileEntityForceEngine) { + engine = (TileEntityForceEngine)tile; + } else { + return; + } + render(engine.isActive, engine.getCycleProgress(), engine.getFacing().ordinal(), x, y, z); + } + + public void render(boolean active, float progress, int facing, double x, double y, double z) { + float step; + GL11.glPushMatrix(); + GL11.glTranslated(x, y, z); + if (progress > 1.0F) + progress = 1.0F; + if (progress > 0.5D) { + step = 8.0F - (progress - 0.5F) * 2.0F * 8.0F; + } else { + step = progress * 16.0F; + } + float translateFactor = step / 16.0F; + base.rotateAngleX = ModelEngine.angleBaseYNeg[facing][0]; + base.rotateAngleY = ModelEngine.angleBaseYNeg[facing][1]; + base.rotateAngleZ = ModelEngine.angleBaseYNeg[facing][2]; + piston.rotateAngleX = ModelEngine.angleBaseYNeg[facing][0]; + piston.rotateAngleY = ModelEngine.angleBaseYNeg[facing][1]; + piston.rotateAngleZ = ModelEngine.angleBaseYNeg[facing][2]; + extension.rotateAngleX = ModelEngine.angleBaseYNeg[facing][0]; + extension.rotateAngleY = ModelEngine.angleBaseYNeg[facing][1]; + extension.rotateAngleZ = ModelEngine.angleBaseYNeg[facing][2]; + Dartcraft.proxy.bindTexture("forceEngine.png"); + base.render(0.0625F); + GL11.glPushMatrix(); + GL11.glTranslated(translate[facing][0] * translateFactor, translate[facing][1] * translateFactor, translate[facing][2] * translateFactor); + piston.render(0.0625F); + GL11.glPopMatrix(); + if (active) { + (trunk[1]).rotateAngleX = ModelEngine.angleBaseYNeg[facing][0]; + (trunk[1]).rotateAngleY = ModelEngine.angleBaseYNeg[facing][1]; + (trunk[1]).rotateAngleZ = ModelEngine.angleBaseYNeg[facing][2]; + trunk[1].render(0.0625F); + } else { + (trunk[0]).rotateAngleX = ModelEngine.angleBaseYNeg[facing][0]; + (trunk[0]).rotateAngleY = ModelEngine.angleBaseYNeg[facing][1]; + (trunk[0]).rotateAngleZ = ModelEngine.angleBaseYNeg[facing][2]; + trunk[0].render(0.0625F); + } + float extensionFactor = 0.125F; + for (int i = 0; i < step + 2.0F; i += 2) { + extension.render(0.0625F); + GL11.glTranslated(translate[facing][0] * extensionFactor, translate[facing][1] * extensionFactor, translate[facing][2] * extensionFactor); + } + GL11.glPopMatrix(); + } + + static { + translate[0][1] = -1.0D; + translate[1][1] = 1.0D; + translate[2][2] = -1.0D; + translate[3][2] = 1.0D; + translate[4][0] = -1.0D; + translate[5][0] = 1.0D; + base = new ModelRenderer(model, 0, 0); + base.setTextureSize(128, 64); + base.addBox(-8.0F, -8.0F, -8.0F, 16, 4, 16); + base.rotationPointX = 8.0F; + base.rotationPointY = 8.0F; + base.rotationPointZ = 8.0F; + piston = new ModelRenderer(model, 64, 0); + piston.setTextureSize(128, 64); + piston.addBox(-7.0F, -4.0F, -7.0F, 14, 4, 14); + piston.rotationPointX = 8.0F; + piston.rotationPointY = 8.0F; + piston.rotationPointZ = 8.0F; + extension = new ModelRenderer(model, 0, 20); + extension.setTextureSize(128, 64); + extension.addBox(-5.0F, -4.5F, -5.0F, 10, 2, 10); + extension.rotationPointX = 8.0F; + extension.rotationPointY = 8.0F; + extension.rotationPointZ = 8.0F; + for (int i = 0; i < 2; i++) { + trunk[i] = new ModelRenderer(model, 32 * i, 44); + trunk[i].setTextureSize(128, 64); + trunk[i].addBox(-4.0F, -4.0F, -4.0F, 8, 12, 8); + (trunk[i]).rotationPointX = 8.0F; + (trunk[i]).rotationPointY = 8.0F; + (trunk[i]).rotationPointZ = 8.0F; + } + } +} diff --git a/src/main/java/ley/modding/dartcraft/client/renderer/item/RenderItemEngine.java b/src/main/java/ley/modding/dartcraft/client/renderer/item/RenderItemEngine.java new file mode 100644 index 0000000..66897b3 --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/client/renderer/item/RenderItemEngine.java @@ -0,0 +1,23 @@ +package ley.modding.dartcraft.client.renderer.item; + +import ley.modding.dartcraft.proxy.ClientProxy; +import net.minecraft.item.ItemStack; +import net.minecraftforge.client.IItemRenderer; + +public class RenderItemEngine implements IItemRenderer { + public boolean handleRenderType(ItemStack item, IItemRenderer.ItemRenderType type) { + return true; + } + + public boolean shouldUseRenderHelper(IItemRenderer.ItemRenderType type, ItemStack item, IItemRenderer.ItemRendererHelper helper) { + return true; + } + + public void renderItem(IItemRenderer.ItemRenderType type, ItemStack item, Object... data) { + if (type == IItemRenderer.ItemRenderType.EQUIPPED || type == IItemRenderer.ItemRenderType.INVENTORY) { + ClientProxy.engineRender.render(false, 0.25F, 1, 0.0D, 0.0D, 0.0D); + } else { + ClientProxy.engineRender.render(false, 0.25F, 1, -0.5D, -0.5D, -0.5D); + } + } +} diff --git a/src/main/java/ley/modding/dartcraft/proxy/ClientProxy.java b/src/main/java/ley/modding/dartcraft/proxy/ClientProxy.java index a7869ca..73b53f7 100644 --- a/src/main/java/ley/modding/dartcraft/proxy/ClientProxy.java +++ b/src/main/java/ley/modding/dartcraft/proxy/ClientProxy.java @@ -1,25 +1,32 @@ package ley.modding.dartcraft.proxy; +import cpw.mods.fml.client.registry.ClientRegistry; import cpw.mods.fml.client.registry.RenderingRegistry; -import cpw.mods.fml.common.network.simpleimpl.IMessage; import ley.modding.dartcraft.Config; import ley.modding.dartcraft.Dartcraft; +import ley.modding.dartcraft.block.DartBlocks; import ley.modding.dartcraft.client.renderer.block.PowerOreRenderer; +import ley.modding.dartcraft.client.renderer.block.RenderTileForceEngine; import ley.modding.dartcraft.client.renderer.entity.RenderColdAnimal; import ley.modding.dartcraft.client.renderer.entity.RenderEntityBottle; +import ley.modding.dartcraft.client.renderer.item.RenderItemEngine; import ley.modding.dartcraft.client.renderer.item.RenderItemForceFlask; import ley.modding.dartcraft.entity.*; import ley.modding.dartcraft.item.DartItems; import ley.modding.dartcraft.network.DartPacket; +import ley.modding.dartcraft.tile.TileEntityForceEngine; import net.minecraft.client.model.ModelChicken; import net.minecraft.client.model.ModelCow; import net.minecraft.client.model.ModelPig; +import net.minecraft.item.Item; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.client.MinecraftForgeClient; public class ClientProxy extends CommonProxy { + public static RenderTileForceEngine engineRender; + public boolean isSimulating(World world) { return world != null && !world.isRemote; } @@ -41,11 +48,14 @@ public class ClientProxy extends CommonProxy { RenderingRegistry.registerEntityRenderingHandler(EntityColdPig.class, new RenderColdAnimal(new ModelPig(), 0.6f, "textures/entity/coldPig.png")); Config.powerOreRenderID = RenderingRegistry.getNextAvailableRenderId(); RenderingRegistry.registerBlockHandler(new PowerOreRenderer()); + engineRender = new RenderTileForceEngine(); + ClientRegistry.bindTileEntitySpecialRenderer(TileEntityForceEngine.class, engineRender); + MinecraftForgeClient.registerItemRenderer(Item.getItemFromBlock(DartBlocks.engine), new RenderItemEngine()); } public void sendPacketToServer(DartPacket packet) { try { - Dartcraft.channel.sendToServer((IMessage)packet); + Dartcraft.channel.sendToServer(packet); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/java/ley/modding/dartcraft/tile/TileEntityForceEngine.java b/src/main/java/ley/modding/dartcraft/tile/TileEntityForceEngine.java new file mode 100644 index 0000000..f6d3692 --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/tile/TileEntityForceEngine.java @@ -0,0 +1,532 @@ +package ley.modding.dartcraft.tile; + +import cofh.api.energy.IEnergyProvider; +import cofh.api.energy.IEnergyReceiver; +import ley.modding.dartcraft.Config; +import ley.modding.dartcraft.Dartcraft; +import ley.modding.dartcraft.api.energy.EngineLiquid; +import ley.modding.dartcraft.item.DartItems; +import ley.modding.dartcraft.util.ForceEngineLiquids; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.ICrafting; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.InventoryBasic; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; +import net.minecraft.network.play.server.S35PacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.*; + +public class TileEntityForceEngine extends TileEntity implements IFluidHandler, IInventory, IEnergyProvider { //TODO Fix GUI + + public static final int MAX_STORED = 50000; + + public static final int MAX_LIQUID = 10000; + + public static final int CYCLE_TIME = 20; + + public InventoryBasic liquidInventory; + + public ItemStack liquidSlot; + + public ForgeDirection facing; + + public boolean isActive; + + public boolean isShutdown; + + public boolean canCycle; + + public boolean stageCycle; + + public float fuelRF; + + public float cycleProgress; + + public int fuelLossCycle; + + public int throttleLossCycle; + + public int packetTime; + + public FluidTank fuelTank; + + public FluidTank throttleTank; + + + public TileEntityForceEngine() { + this.fuelTank = new FluidTank(10000); + this.throttleTank = new FluidTank(10000); + this.fuelLossCycle = this.throttleLossCycle = 0; + this.liquidInventory = new InventoryBasic("forceEngine.stacks", false, 2); + this.liquidInventory.setInventorySlotContents(0, (ItemStack)null); + this.liquidInventory.setInventorySlotContents(1, (ItemStack)null); + this.facing = ForgeDirection.UP; + } + + + public ForgeDirection getFacing() { + return this.facing; + } + + public float getCycleProgress() { + return this.cycleProgress; + } + + public boolean setFacing(ForgeDirection dir) { + this.facing = dir; + return true; + } + + public boolean rotateBlock() { + for(int i = this.facing.ordinal() + 1; i < this.facing.ordinal() + 6; ++i) { + ForgeDirection dir = ForgeDirection.VALID_DIRECTIONS[i % 6]; + TileEntity tile = this.worldObj.getTileEntity(xCoord + dir.offsetX, yCoord + dir.offsetY, zCoord + dir.offsetZ); + if(tile instanceof IEnergyReceiver && ((IEnergyReceiver) tile).canConnectEnergy(dir.getOpposite())) { + this.facing = dir; + this.worldObj.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord); + this.worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, worldObj.getBlock(xCoord, yCoord, zCoord)); + return true; + } + } + + return false; + } + + public int getLightValue() { + return this.isActive ? 7 : 0; + } + + protected boolean canCycle() { + TileEntity tile = this.worldObj.getTileEntity(xCoord + facing.offsetX, yCoord + facing.offsetY, zCoord + facing.offsetZ); + if(tile instanceof IEnergyReceiver) { + this.canCycle = true; + } else { + this.canCycle = false; + } + + return this.canCycle; + } + + protected boolean canProcess() { + return this.fuelTank.getFluid() != null && this.fuelTank.getFluid().amount > 0; + } + + public float getEnergyPerProcess() { + if(this.fuelTank.getFluid() == null) { + return 0.0F; + } else { + EngineLiquid fuel = ForceEngineLiquids.getEngineLiquid(this.fuelTank.getFluid()); + EngineLiquid throttle = null; + if(this.throttleTank.getFluid() != null) { + throttle = ForceEngineLiquids.getEngineLiquid(this.throttleTank.getFluid()); + } + + if(fuel == null) { + return 0.0F; + } else { + float energy = fuel.getModifier(); + if(throttle != null) { + energy *= throttle.getModifier(); + } + + return energy; + } + } + } + + private void doLoss() { + if(this.fuelTank.getFluid() != null) { + EngineLiquid fuel = ForceEngineLiquids.getEngineLiquid(this.fuelTank.getFluid()); + EngineLiquid throttle = null; + if(this.throttleTank.getFluid() != null) { + throttle = ForceEngineLiquids.getEngineLiquid(this.throttleTank.getFluid()); + } + + FluidStack var10000; + if(fuel != null) { + ++this.fuelLossCycle; + if(this.fuelLossCycle >= fuel.getBurnTime() / 1000) { + var10000 = this.fuelTank.getFluid(); + var10000.amount -= 1000 / fuel.getBurnTime() > 0?1000 / fuel.getBurnTime():1; + this.fuelLossCycle = 0; + } + } + + if(throttle != null) { + ++this.throttleLossCycle; + if(this.throttleLossCycle >= throttle.getBurnTime() / 1000) { + var10000 = this.throttleTank.getFluid(); + var10000.amount -= 1000 / throttle.getBurnTime() > 0?1000 / throttle.getBurnTime():1; + this.throttleLossCycle = 0; + } + } + + if(this.fuelTank.getFluid() != null && this.fuelTank.getFluid().amount <= 0) { + this.fuelTank.setFluid(null); + } + + if(this.throttleTank.getFluid() != null && this.throttleTank.getFluid().amount <= 0) { + this.throttleTank.setFluid(null); + } + + } + } + + public void processActive() { + this.doLoss(); + } + + protected void transferEnergy() { //TODO better energy transfer + TileEntity tile = this.worldObj.getTileEntity(xCoord + facing.offsetX, yCoord + facing.offsetY, zCoord + facing.offsetZ); + if(tile instanceof IEnergyReceiver && ((IEnergyReceiver) tile).canConnectEnergy(facing.getOpposite())) { + int energy = (int) this.getEnergyPerProcess() * 200; + ((IEnergyReceiver) tile).receiveEnergy(facing.getOpposite(), energy, false); + } + + } + + + public void updateEntity() { + if(!Dartcraft.proxy.isSimulating(worldObj)) { + if(this.cycleProgress > 0.0F || this.isActive && this.canCycle) { + this.cycleProgress += 0.04F; + if(this.cycleProgress >= 1.0F) { + this.cycleProgress = 0.0F; + } + } + + } else { + FluidStack curActive; + if(this.liquidInventory.getStackInSlot(0) != null) { + curActive = FluidContainerRegistry.getFluidForFilledItem(this.liquidInventory.getStackInSlot(0)); + Fluid curCycle = FluidRegistry.getFluid("liquidforce"); + if(curActive != null) { + EngineLiquid temp = ForceEngineLiquids.getEngineLiquid(curActive); + if(temp != null && (this.fuelTank.getFluid() == null || this.fuelTank.getFluid().isFluidEqual(curActive)) && (this.fuelTank.getFluid() == null || 10000 >= this.fuelTank.getFluid().amount + curActive.amount)) { + this.fuelTank.fill(curActive, true); + ItemStack temp1 = this.liquidInventory.getStackInSlot(0); + if(temp1.stackSize == 1 && temp1.getItem().hasContainerItem()) { + this.liquidInventory.setInventorySlotContents(0, temp1.getItem().getContainerItem(temp1)); + } else { + this.liquidInventory.decrStackSize(0, 1); + } + } + } + + if(this.liquidInventory.getStackInSlot(0) != null && this.liquidInventory.getStackInSlot(0).getItem() == DartItems.forcegem && curCycle != null && (this.fuelTank.getFluid() == null || 10000 >= this.fuelTank.getFluid().amount + (int)(1000.0F * Config.gemValue))) { + this.fuelTank.fill(new FluidStack(curCycle, (int)(1000.0F * Config.gemValue)), true); + this.liquidInventory.decrStackSize(0, 1); + } + } + + if(this.liquidInventory.getStackInSlot(1) != null) { + curActive = FluidContainerRegistry.getFluidForFilledItem(this.liquidInventory.getStackInSlot(1)); + if(curActive != null) { + EngineLiquid curCycle1 = ForceEngineLiquids.getEngineLiquid(curActive); + if(curCycle1 != null && (this.throttleTank.getFluid() == null || this.throttleTank.getFluid().isFluidEqual(curActive)) && (this.throttleTank.getFluid() == null || 10000 >= this.throttleTank.getFluid().amount + curActive.amount)) { + this.throttleTank.fill(curActive, true); + ItemStack temp2 = this.liquidInventory.getStackInSlot(1); + if(temp2.stackSize == 1 && temp2.getItem().hasContainerItem()) { + this.liquidInventory.setInventorySlotContents(1, temp2.getItem().getContainerItem(temp2)); + } else { + this.liquidInventory.decrStackSize(1, 1); + } + } + } + } + + if(this.cycleProgress > 0.0F || this.isActive && this.canCycle) { + this.cycleProgress += 0.04F; + if(this.cycleProgress >= 1.0F) { + this.cycleProgress = 0.0F; + this.stageCycle = false; + } else if((double)this.cycleProgress >= 0.5D && !this.stageCycle) { + this.transferEnergy(); + this.stageCycle = true; + } + } + + if(this.worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord) && this.canCycle()) { + if(this.canProcess()) { + this.isActive = true; + this.processActive(); + } else { + this.isActive = false; + } + } else { + this.isActive = false; + } + //TODO Fix Cycling update + } + } + + public void readFromNBT(NBTTagCompound data) { + super.readFromNBT(data); + this.facing = ForgeDirection.getOrientation(data.getByte("facing")); + this.isActive = data.getBoolean("active"); + this.fuelRF = data.getFloat("fuelRF"); + this.canCycle = data.getBoolean("cycle"); + if(data.hasKey("fuel")) { + this.fuelTank.setFluid(FluidStack.loadFluidStackFromNBT(data.getCompoundTag("fuel"))); + } + + if(data.hasKey("throttle")) { + this.throttleTank.setFluid(FluidStack.loadFluidStackFromNBT(data.getCompoundTag("throttle"))); + } + + if(data.hasKey("fuelSlot")) { + this.liquidInventory.setInventorySlotContents(0, ItemStack.loadItemStackFromNBT(data.getCompoundTag("fuelSlot"))); + } else { + this.liquidInventory.setInventorySlotContents(0, (ItemStack)null); + } + + if(data.hasKey("throttleSlot")) { + this.liquidInventory.setInventorySlotContents(1, ItemStack.loadItemStackFromNBT(data.getCompoundTag("throttleSlot"))); + } else { + this.liquidInventory.setInventorySlotContents(1, (ItemStack)null); + } + + } + + public void writeToNBT(NBTTagCompound data) { + super.writeToNBT(data); + data.setByte("facing", (byte)this.facing.ordinal()); + data.setBoolean("active", this.isActive); + data.setFloat("fuelRF", this.fuelRF); + data.setBoolean("cycle", this.canCycle); + if(this.fuelTank.getFluid() != null) { + data.setTag("fuel", this.fuelTank.getFluid().writeToNBT(new NBTTagCompound())); + } + + if(this.throttleTank.getFluid() != null) { + data.setTag("throttle", this.throttleTank.getFluid().writeToNBT(new NBTTagCompound())); + } + + if(this.liquidInventory.getStackInSlot(0) != null) { + data.setTag("fuelSlot", this.liquidInventory.getStackInSlot(0).writeToNBT(new NBTTagCompound())); + } + + if(this.liquidInventory.getStackInSlot(1) != null) { + data.setTag("throttleSlot", this.liquidInventory.getStackInSlot(1).writeToNBT(new NBTTagCompound())); + } + + } + + + @Override + public int extractEnergy(ForgeDirection var1, int var2, boolean var3) { + return 0; + } + + @Override + public int getEnergyStored(ForgeDirection var1) { + return 0; + } + + @Override + public int getMaxEnergyStored(ForgeDirection var1) { + return 0; + } + + @Override + public boolean canConnectEnergy(ForgeDirection var1) { + return var1 == facing; + } + + @Override + public int getSizeInventory() { + return this.liquidInventory.getSizeInventory(); + } + + @Override + public ItemStack getStackInSlot(int i) { + return this.liquidInventory.getStackInSlot(i); + } + + @Override + public ItemStack decrStackSize(int i, int j) { + return this.liquidInventory.decrStackSize(i, j); + } + + @Override + public ItemStack getStackInSlotOnClosing(int i) { + return this.liquidInventory.getStackInSlotOnClosing(i); + } + + @Override + public void setInventorySlotContents(int i, ItemStack stack) { + this.liquidInventory.setInventorySlotContents(i, stack); + } + + @Override + public String getInventoryName() { + return this.liquidInventory.getInventoryName(); + } + + @Override + public boolean hasCustomInventoryName() { + return this.liquidInventory.hasCustomInventoryName(); + } + + @Override + public int getInventoryStackLimit() { + return this.liquidInventory.getInventoryStackLimit(); + } + + @Override + public boolean isUseableByPlayer(EntityPlayer player) { + return this.liquidInventory.isUseableByPlayer(player); + } + + @Override + public void openInventory() { + this.liquidInventory.openInventory(); + } + + @Override + public void closeInventory() { + this.liquidInventory.closeInventory(); + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack stack) { + switch(i) { + case 0: + return ForceEngineLiquids.isFuel(FluidContainerRegistry.getFluidForFilledItem(stack)); + case 1: + return ForceEngineLiquids.isThrottle(FluidContainerRegistry.getFluidForFilledItem(stack)); + default: + return false; + } + } + + @Override + public int fill(ForgeDirection from, FluidStack resource, boolean doFill) { + int filled; + if(ForceEngineLiquids.isFuel(resource)) { + filled = this.fuelTank.fill(resource, doFill); + return filled; + } else if(ForceEngineLiquids.isThrottle(resource)) { + filled = this.throttleTank.fill(resource, doFill); + return filled; + } else { + return 0; + } + } + + @Override + public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) { + return null; + } + + @Override + public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) { + return null; + } + + @Override + public boolean canFill(ForgeDirection from, Fluid fluid) { + return (from != null && fluid != null) && this.fill(from, new FluidStack(fluid, 1), false) > 0; + } + + @Override + public boolean canDrain(ForgeDirection from, Fluid fluid) { + return false; + } + + @Override + public FluidTankInfo[] getTankInfo(ForgeDirection from) { + return new FluidTankInfo[]{this.fuelTank.getInfo(), this.throttleTank.getInfo()}; + } + + public Packet getDescriptionPacket() { + NBTTagCompound comp = new NBTTagCompound(); + this.writeToNBT(comp); + return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 0, comp); + } + + public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { + if(pkt != null && pkt.func_148857_g() != null) { + this.readFromNBT(pkt.func_148857_g()); + worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); //TODO Lighting + //worldObj.updateAllLightTypes(this.field_70329_l, this.field_70330_m, this.field_70327_n); + } + + } + + public void sendGuiNetworkData(Container container, ICrafting craft) { + byte throttleMeta = 0; + int throttleID = 0; + int throttleAmount = 0; + byte fuelMeta = 0; + int fuelID = 0; + int fuelAmount = 0; + if(this.fuelTank.getFluid() != null) { + fuelID = this.fuelTank.getFluid().getFluidID(); + fuelAmount = this.fuelTank.getFluid().amount; + } + + if(this.throttleTank.getFluid() != null) { + throttleID = this.throttleTank.getFluid().getFluidID(); + throttleAmount = this.throttleTank.getFluid().amount; + } + + craft.sendProgressBarUpdate(container, 0, fuelID); + craft.sendProgressBarUpdate(container, 1, fuelMeta); + craft.sendProgressBarUpdate(container, 2, fuelAmount); + craft.sendProgressBarUpdate(container, 3, throttleID); + craft.sendProgressBarUpdate(container, 4, throttleMeta); + craft.sendProgressBarUpdate(container, 5, throttleAmount); + if(craft instanceof EntityPlayerMP && Dartcraft.proxy.isSimulating(worldObj)) { + ((EntityPlayerMP) craft).playerNetServerHandler.sendPacket(getDescriptionPacket()); + } + } + + public void receiveGuiNetworkData(int i, int j) { + FluidStack tempStack = this.fuelTank.getFluid(); + FluidStack tempStack2 = this.throttleTank.getFluid(); + switch(i) { + case 0: + if(this.fuelTank.getFluid() != null) { + this.fuelTank.setFluid(new FluidStack(j, tempStack.amount, tempStack.tag)); + } else if (j > 0) { + this.fuelTank.setFluid(new FluidStack(j, 0)); + } + break; + case 1: + if(this.fuelTank.getFluid() != null) { + this.fuelTank.setFluid(new FluidStack(tempStack.getFluidID(), tempStack.amount, (NBTTagCompound)null)); + } + break; + case 2: + if(this.fuelTank.getFluid() != null) { + this.fuelTank.getFluid().amount = j; + } + break; + case 3: + if(this.throttleTank.getFluid() != null) { + this.throttleTank.setFluid(new FluidStack(j, tempStack2.amount, tempStack2.tag)); + } else if (j > 0) { + this.throttleTank.setFluid(new FluidStack(j, 0)); + } + break; + case 4: + if(this.throttleTank.getFluid() != null) { + this.throttleTank.setFluid(new FluidStack(tempStack2.getFluidID(), tempStack2.amount, (NBTTagCompound)null)); + } + break; + case 5: + if(this.throttleTank.getFluid() != null) { + this.throttleTank.getFluid().amount = j; + } + } + + } + +} diff --git a/src/main/java/ley/modding/dartcraft/util/DartUtils.java b/src/main/java/ley/modding/dartcraft/util/DartUtils.java new file mode 100644 index 0000000..f6513fb --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/util/DartUtils.java @@ -0,0 +1,83 @@ +package ley.modding.dartcraft.util; + +import buildcraft.api.tools.IToolWrench; +import ley.modding.dartcraft.Dartcraft; +import ley.modding.dartcraft.proxy.CommonProxy; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidContainerRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidHandler; + +public class DartUtils { + + public static boolean isHoldingWrench(EntityPlayer player) { + if(player.getCurrentEquippedItem() == null) { + return false; + } else { + Item equipped = player.getCurrentEquippedItem().getItem(); + return equipped instanceof IToolWrench; + } + } + + public static boolean fillTankWithContainer(IFluidHandler theTile, EntityPlayer player) { + ItemStack theContainer = player.getCurrentEquippedItem(); + FluidStack theLiquid = FluidContainerRegistry.getFluidForFilledItem(theContainer); + if(theLiquid != null && (theTile.fill(ForgeDirection.UNKNOWN, theLiquid, false) == theLiquid.amount || player.capabilities.isCreativeMode)) { + theTile.fill(ForgeDirection.UNKNOWN, theLiquid, true); + ItemStack returnStack = consumeItem(theContainer); + if(!player.capabilities.isCreativeMode) { + player.inventory.setInventorySlotContents(player.inventory.currentItem, returnStack); + } + + return true; + } else { + return false; + } + } + + public static ItemStack consumeItem(ItemStack theStack) { + if(theStack.stackSize == 1) { + return theStack.getItem().hasContainerItem()?theStack.getItem().getContainerItem(theStack):null; + } else { + theStack.splitStack(1); + return theStack; + } + } + + public static void dropItem(ItemStack stack, World world, double x, double y, double z) { + if(stack != null && world != null && Dartcraft.proxy.isSimulating(world)) { + float xRand = CommonProxy.rand.nextFloat() * 0.2F + 0.1F; + float yRand = CommonProxy.rand.nextFloat() * 0.8F + 0.1F; + float zRand = CommonProxy.rand.nextFloat() * 0.2F + 0.1F; + + while(stack.stackSize > 0) { + int randInt = CommonProxy.rand.nextInt(21) + 10; + if(randInt > stack.stackSize) { + randInt = stack.stackSize; + } + + stack.stackSize -= randInt; + EntityItem droppedItem = new EntityItem(world, (double)((float)x + xRand), (double)((float)y + yRand), (double)((float)z + zRand), new ItemStack(stack.getItem(), randInt, stack.getItemDamage())); + if(stack.hasTagCompound()) { + droppedItem.getEntityItem().setTagCompound((NBTTagCompound)stack.getTagCompound().copy()); + } + + float modifier = 0.025F; + CommonProxy var10001 = Dartcraft.proxy; + droppedItem.motionX = (double)((float)CommonProxy.rand.nextGaussian() * modifier); + droppedItem.motionY = (double)((float)CommonProxy.rand.nextGaussian() * modifier + 0.2F); + droppedItem.motionZ = (double)((float)CommonProxy.rand.nextGaussian() * modifier); + droppedItem.delayBeforeCanPickup = 10; + world.spawnEntityInWorld(droppedItem); + } + } + + } + +} diff --git a/src/main/java/ley/modding/dartcraft/util/ForceConsumerUtils.java b/src/main/java/ley/modding/dartcraft/util/ForceConsumerUtils.java index b8b47a7..1f9b62e 100644 --- a/src/main/java/ley/modding/dartcraft/util/ForceConsumerUtils.java +++ b/src/main/java/ley/modding/dartcraft/util/ForceConsumerUtils.java @@ -1,12 +1,15 @@ package ley.modding.dartcraft.util; import ley.modding.dartcraft.Config; +import ley.modding.dartcraft.Dartcraft; import ley.modding.dartcraft.api.IForceConsumer; import ley.modding.dartcraft.api.inventory.ItemInventory; import ley.modding.dartcraft.item.DartItems; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidContainerRegistry; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; @@ -112,4 +115,29 @@ public class ForceConsumerUtils { return canUse; } + public static boolean isForceContainer(ItemStack stack) + { + if (stack == null) { + return false; + } + FluidStack liquid = FluidContainerRegistry.getFluidForFilledItem(stack); + Fluid liquidForce = FluidRegistry.getFluid("liquidforce"); + + if ((liquid != null) && (liquidForce != null) && (liquid.getFluidID() == liquidForce.getID())) { + return true; + } + return (stack.getItem() == DartItems.forcegem) || (stack.getItem() == DartItems.forceshard); + } + + public static boolean openForceConsumerGui(EntityPlayer player, ItemStack stack) + { + if ((stack == null) || (stack.getItem() == null) || (!stack.hasTagCompound()) || (!(stack.getItem() instanceof IForceConsumer)) || (player == null)) + { + return false; + } + + player.openGui(Dartcraft.instance, 16, player.worldObj, (int)player.posX, (int)player.posY, (int)player.posZ); + return true; + } + } diff --git a/src/main/java/ley/modding/dartcraft/util/ForceEngineLiquids.java b/src/main/java/ley/modding/dartcraft/util/ForceEngineLiquids.java new file mode 100644 index 0000000..32b6252 --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/util/ForceEngineLiquids.java @@ -0,0 +1,290 @@ +package ley.modding.dartcraft.util; + +import ley.modding.dartcraft.Config; +import ley.modding.dartcraft.api.energy.EngineLiquid; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidContainerRegistry; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +public class ForceEngineLiquids { + + private static ArrayList fuels = new ArrayList(); + private static ArrayList throttles = new ArrayList(); + + + public static void load() { + assertMilk(); + new ArrayList(); + boolean defaults = false; + ArrayList input = Config.getFuels(); + if(input == null || input.size() <= 0) { + defaults = true; + } + + try { + ArrayList e = getValues(input); + HashMap fuels = (HashMap)e.get(0); + HashMap throttles = (HashMap)e.get(1); + if(defaults || fuels.size() < 1 || throttles.size() < 1 || !fuels.containsKey("liquidforce")) { + throw new Exception(); + } + + Iterator i$ = fuels.keySet().iterator(); + + String name; + FluidStack e1; + EngineLiquid throttle; + while(i$.hasNext()) { + name = (String)i$.next(); + + try { + e1 = new FluidStack(FluidRegistry.getFluid(name), 1000); + throttle = new EngineLiquid(e1, 0, (int)((float[])fuels.get(name))[1], ((float[])fuels.get(name))[0]); + addLiquid(throttle); + } catch (Exception err) { + err.printStackTrace(); + } + } + + i$ = throttles.keySet().iterator(); + + while(i$.hasNext()) { + name = (String)i$.next(); + + try { + e1 = new FluidStack(FluidRegistry.getFluid(name), 1000); + throttle = new EngineLiquid(e1, 1, (int)((float[])throttles.get(name))[1], ((float[])throttles.get(name))[0]); + addLiquid(throttle); + } catch (Exception err) { + err.printStackTrace(); + } + } + } catch (Exception e) { + // Dartcraft..warning("There was an error loading the fuels.txt. Please configure it correctly."); + e.printStackTrace(); + defaults = true; + } + + if(defaults) { + //DartCraft.dartLog.info("Loading default Fuels."); + vanillaSupport(); + buildcraftSupport(); + forestrySupport(); + } + + } + + private static void assertMilk() { + try { + if(FluidRegistry.isFluidRegistered("milk") && FluidContainerRegistry.getFluidForFilledItem(new ItemStack(Items.milk_bucket)) == null) { + Fluid e = FluidRegistry.getFluid("milk"); + FluidStack milkStack = new FluidStack(e, 1000); + FluidContainerRegistry.registerFluidContainer(new FluidContainerRegistry.FluidContainerData(milkStack, new ItemStack(Items.milk_bucket), FluidContainerRegistry.EMPTY_BUCKET)); + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + private static ArrayList getValues(ArrayList input) { + ArrayList values = new ArrayList(); + HashMap fuels = new HashMap(); + HashMap throttles = new HashMap(); + + try { + Iterator e = input.iterator(); + + while(e.hasNext()) { + String check = (String)e.next(); + if(check != null && check.length() > 0) { + try { + String e1 = ""; + float value = 0.0F; + boolean time = false; + int time1; + switch(check.charAt(0)) { + case 102: + e1 = check.substring(2, check.indexOf(61)); + if(!fuels.containsKey(e1) && FluidRegistry.getFluid(e1) != null) { + value = (new Float(check.substring(check.indexOf(61) + 1, check.indexOf(59)))).floatValue(); + time1 = (new Integer(check.substring(check.indexOf(59) + 1))).intValue(); + if(value < 0.5F) { + value = 0.5F; + } + + if(value > 20.0F) { + value = 20.0F; + } + + if(time1 < 100) { + time1 = 100; + } + + if(time1 > 1000000) { + time1 = 1000000; + } + + fuels.put(e1, new float[]{value, (float)time1}); + } + break; + case 116: + e1 = check.substring(2, check.indexOf(61)); + if(!throttles.containsKey(e1) && FluidRegistry.getFluid(e1) != null) { + value = (new Float(check.substring(check.indexOf(61) + 1, check.indexOf(59)))).floatValue(); + time1 = (new Integer(check.substring(check.indexOf(59) + 1))).intValue(); + if(value < 1.0F) { + value = 1.0F; + } + + if(value > 20.0F) { + value = 20.0F; + } + + if(time1 < 100) { + time1 = 100; + } + + if(time1 > 1000000) { + time1 = 1000000; + } + + throttles.put(e1, new float[]{value, (float)time1}); + } + } + } catch (Exception e1) { + e1.printStackTrace(); + } + } + } + } catch (Exception e2) { + e2.printStackTrace(); + } + + values.add(fuels); + values.add(throttles); + return values; + } + + private static void vanillaSupport() { + Fluid liquidForce = FluidRegistry.getFluid("liquidforce"); + FluidStack milk = FluidRegistry.getFluidStack("milk", 1000); + if(liquidForce != null) { + addLiquid(new EngineLiquid(new FluidStack(liquidForce, 1000), 0, 20000, 4.0F)); + } + + if(milk != null) { + addLiquid(new EngineLiquid(milk, 1, 3000, 2.5F)); + } + + addLiquid(new EngineLiquid(new FluidStack(FluidRegistry.WATER, 1000), 1, 600, 2.0F)); + addLiquid(new EngineLiquid(new FluidStack(FluidRegistry.LAVA, 1000), 0, 20000, 0.5F)); + } + + private static void buildcraftSupport() { + FluidStack oil = FluidRegistry.getFluidStack("oil", 1000); + if(oil != null) { + addLiquid(new EngineLiquid(oil, 0, 20000, 1.5F)); + } + + FluidStack fuel = FluidRegistry.getFluidStack("fuel", 1000); + if(fuel != null) { + addLiquid(new EngineLiquid(fuel, 0, 100000, 3.0F)); + } + + } + + private static void forestrySupport() { + FluidStack crushedIce = FluidRegistry.getFluidStack("ice", 1000); + if(crushedIce != null) { + addLiquid(new EngineLiquid(crushedIce, 1, 20000, 4.0F)); + } + + FluidStack ethanol = FluidRegistry.getFluidStack("bioethanol", 1000); + if(ethanol != null) { + addLiquid(new EngineLiquid(ethanol, 0, '\uea60', 2.0F)); + } + + } + + public static void addLiquid(EngineLiquid liquid) { + if(liquid != null) { + if(liquid.getType() == 0 && !isThrottle(liquid.getLiquid())) { + fuels.add(liquid); + System.out.println("Added fuel: " + liquid.getLiquid().getFluid().getName()); + } + + if(liquid.getType() == 1 && !isFuel(liquid.getLiquid())) { + throttles.add(liquid); + System.out.println("Added throttle: " + liquid.getLiquid().getFluid().getName()); + } + + } + } + + public static boolean isFuel(FluidStack liquid) { + if(fuels != null && fuels.size() > 0 && liquid != null) { + Iterator i$ = fuels.iterator(); + + while(i$.hasNext()) { + EngineLiquid fuel = (EngineLiquid)i$.next(); + if(fuel != null && fuel.getLiquid() != null && fuel.getLiquid().isFluidEqual(liquid)) { + return true; + } + } + } + + return false; + } + + public static boolean isThrottle(FluidStack liquid) { + if(throttles != null && throttles.size() > 0 && liquid != null) { + Iterator i$ = throttles.iterator(); + + while(i$.hasNext()) { + EngineLiquid throttle = (EngineLiquid) i$.next(); + if(throttle != null && throttle.getLiquid() != null && throttle.getLiquid().isFluidEqual(liquid)) { + return true; + } + } + } + + return false; + } + + public static EngineLiquid getEngineLiquid(FluidStack liquid) { + Iterator i$; + EngineLiquid throttle; + if(fuels != null && fuels.size() > 0 && liquid != null) { + i$ = fuels.iterator(); + + while(i$.hasNext()) { + throttle = (EngineLiquid)i$.next(); + if(throttle != null && throttle.getLiquid() != null && throttle.getLiquid().isFluidEqual(liquid)) { + return throttle; + } + } + } + + if(throttles != null && throttles.size() > 0 && liquid != null) { + i$ = throttles.iterator(); + + while(i$.hasNext()) { + throttle = (EngineLiquid)i$.next(); + if(throttle != null && throttle.getLiquid() != null && throttle.getLiquid().isFluidEqual(liquid)) { + return throttle; + } + } + } + + return null; + } + +} diff --git a/src/main/java/ley/modding/dartcraft/util/FortunesUtil.java b/src/main/java/ley/modding/dartcraft/util/FortunesUtil.java new file mode 100644 index 0000000..1e6d29c --- /dev/null +++ b/src/main/java/ley/modding/dartcraft/util/FortunesUtil.java @@ -0,0 +1,220 @@ +package ley.modding.dartcraft.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class FortunesUtil { + + private static Random rand; + + private static List fortunes = new ArrayList(); + + public static void addFortune(String fortune) { + if (fortunes != null && fortune != null) + fortunes.add(fortune); + } + + public static void load() { + rand = new Random(System.nanoTime()); + loadFortunes(); + } + + public static String getFortune() { + if (fortunes == null || fortunes.size() < 1) + return ""; + int index = rand.nextInt(fortunes.size()); + if (index >= fortunes.size()) + return ""; + return fortunes.get(index); + } + + private static void loadFortunes() { + addFortune("You aren't supposed to eat me."); + addFortune("Beauty is in the eye of the tiger."); + addFortune("Creeper!"); + addFortune("Which came first, the chicken or the chunk?"); + addFortune("Whatever happened to Doritos 3D?"); + addFortune("Diabetes, anyone?"); + addFortune("That wasn't a cookie!"); + addFortune("If a tree falls down in the woods, you have a special mod installed."); + addFortune("The cake is a lie of omission."); + addFortune("A wise man once said, \"Yes honey, it does make you look fat.\" He never said that again."); + addFortune("Don't stare directly at the pixels."); + addFortune("I know where you live."); + addFortune("Your lucky numbers are 0, -7, and 437922904678137496.708162"); + addFortune("There is never enough redstone."); + addFortune("What you seek is surrounded by blocks."); + addFortune("Today is Tuesday, or is it Friday - I can never tell."); + addFortune("In the event of a creeper explosion, your keyboard can double as a broken keyboard."); + addFortune("I didn't do it."); + addFortune("You are 5.6 grams heavier than you were 10 seconds ago."); + addFortune("I dropped my cookie."); + addFortune("...Saltpeter? Really?"); + addFortune("We're no strangers to love. You know the rules and so do I."); + addFortune("Eat another cookie."); + addFortune("fontRenderer.drawString(\"Totally Real Accidental Glitch\", posX, posY, 0xFFFFFF);"); + addFortune("I CAN believe it's not butter."); + addFortune("Beware enderman with a short fuse..."); + addFortune("Remember to repair your tools."); + addFortune("Every rose has its bounding box."); + addFortune("Get out of my chest!"); + addFortune("Please recycle."); + addFortune("Great, now you've spoiled your dinner!"); + addFortune("Welcome to Hoarders: Minecraft edition!"); + addFortune("Not all Blocks are created equal."); + addFortune("Don't touch that!"); + addFortune("Always name your machinations."); + addFortune("Look in your inventory, now back to me - this fortune is now diamonds!"); + addFortune("Who put that there?"); + addFortune("Winners never cheat and cheaters never win, unless the winners cheated, in which case the cheaters won."); + addFortune("Hi Bob! What, they can't all be zingers."); + addFortune("Have you ever thought to yourself, \"My, that's an awfully large open grave!\""); + addFortune("Could you pick up my dry-cleaning?"); + addFortune("Never shower in a thunderstorm. It's less efficient than bathing indoors and you'll freak out your neighbors."); + addFortune("It is said that everyone experiences hardships, but God must REALLY hate YOU."); + addFortune("If you play a country song backwards, you waste about 4 minutes of your life listening to garbled nonsense."); + addFortune("No, you can't make that jump."); + addFortune("I know they're furry and cuddly, but trust me, they're evil incarnate."); + addFortune("Do you Dew?"); + addFortune("I see the land, but where exactly are the tracts?"); + addFortune("Creepers were originally from Dr. Who."); + addFortune("Don't bogart my nasal spray!"); + addFortune("You'll live."); + addFortune("Don't make me come back there!"); + addFortune("I've burned everything that reminds me of you in a ritualistic bonfire."); + addFortune("We will be an unstoppable force; to our enemies we bring only death, to our allies we always bring cake."); + addFortune("Heavy is the head that eats the crayons."); + addFortune("Beware skinwalkers."); + addFortune("Don't fear the creeper."); + addFortune("Goodness and love will always win!"); + addFortune("I told you not to eat that!"); + addFortune("Winner!"); + addFortune("Beware anyone without an eye-patch!"); + addFortune("Don't kill all the animals!"); + addFortune("It's a wonder you get anything done!"); + addFortune("You will find happiness with a new love: Minecraft's latest patch."); + addFortune("Seriously, who is in charge of the song/cowbell ratio?"); + addFortune("It's not a bug, it's a \"feature.\""); + addFortune("Do you really need this many cookies?"); + addFortune("NCC1701"); + addFortune("I wanted to be a newspaper."); + addFortune("Thank you! It was really dark in there!"); + addFortune("Thank you for not eating me."); + addFortune("Burn the door!"); + addFortune("That's the biggest flapjack I've ever seen!"); + addFortune("Please be kind, de-rind"); + addFortune("It's a secret to everybody."); + addFortune("I AM ERROR."); + addFortune("If all else fails use fire."); + addFortune("Dig it! Dig it! Dig to the center of the earth!"); + addFortune("No! Not into the pit! It BURNS!"); + addFortune("Dawn of the First Day, 72 hours remain."); + addFortune("Don't stare directly at the potato."); + addFortune("The chicken is a double-agent."); + addFortune("Good lord!"); + addFortune("What's all this junk?"); + addFortune("Creepers blow chunks."); + addFortune("Equivalence is a lie."); + addFortune("Body by Sycamore."); + addFortune("I hear 'Innards of the Machine' is on tour."); + addFortune("Do something else."); + addFortune("The capital of The Ukraine is Kiev."); + addFortune("DebugCookie4A73N82"); + addFortune("Point that somewhere else!"); + addFortune("Forking is strictly prohibited."); + addFortune("Void where prohibited."); + addFortune("This parrot is no more!"); + addFortune("He's dead, Jim."); + addFortune("Leave me alone for a bit, okay?"); + addFortune("Don't you dare shift-click me!"); + addFortune("Me again."); + addFortune("My summer home is a no-bake."); + addFortune("We can still be friends."); + addFortune("The night is young, but you are not."); + addFortune("Keyboard cat has carpal tunnel."); + addFortune("Pull lever, get key."); + addFortune("Boats n' Hoes"); + addFortune("Never eat an entire chocolate bunny in one sitting."); + addFortune("Push that button and die."); + addFortune("That cookie was mostly spackle."); + addFortune("Slime Chunkery."); + addFortune("I hate Thaumic Slimes."); + addFortune("Inertia is a property of mallard."); + addFortune("I prefer cake."); + addFortune("If you can read this, you're literate."); + addFortune("Don't touch the sides!"); + addFortune("Crunchitize me Cap'n!"); + addFortune("Please head in an orderly fashion to the disintegration chamber."); + addFortune("It's the deer's ears."); + addFortune("Happy anniversary, Carol!"); + addFortune("Never startle a ninja."); + addFortune("If the shoe fits, you probably own it."); + addFortune("Cattle reproduce by budding."); + addFortune("Has anyone seen my Fedora?"); + addFortune("I beg to defer."); + addFortune("Everybody loops."); + addFortune("Why is Count Chocula seasonal? Pedophilic vampires are always in style!"); + addFortune("Eekum Bokum."); + addFortune("Churba wurt!"); + addFortune("Darwa jit!"); + addFortune("Success is often preceded by failure, then followed again by failure."); + addFortune("Man with Steve skin receive no cake."); + addFortune("It's all Melnics to me!"); + addFortune("\"Steve\" means \"lazy\" in Swedish."); + addFortune("This is the word of Notch."); + addFortune("Don't attack the cute little endermen - you'll be sorry."); + addFortune("I miss my sanity, but then again I never used it."); + addFortune("So this is where germs are born!"); + addFortune("I hate mondays."); + addFortune("My old nemesis: gravity."); + addFortune("I'm upgrade fodder!"); + addFortune("You can do anything at Zombo.com."); + addFortune("Remember to feed the cattle."); + addFortune("TROGDOR was a man. I mean, he was a dragon-man... Maybe he was just a dragon."); + addFortune("Charles in charge of our clicks left and right. Charles in charge of every block in sight."); + addFortune("Charles was never really in charge."); + addFortune("Remember to use every part of the chicken."); + addFortune("I'm not responsible for this."); + addFortune("Every 10 minutes another crappy fortune is written."); + addFortune("How many licks does it take to get to the center of a Chuck Norris?"); + addFortune("Roundhouse-kick for the win!"); + addFortune("DO NOT feed the beast! (After midnight)"); + addFortune("Please stop doing that."); + addFortune("I'm not a vending machine!"); + addFortune("Try Ubuntu."); + addFortune("If you program for more than 20 hours straight, do not blink."); + addFortune("Ceiling cat is watching you procrastinate."); + addFortune("Get your hand off my thigh! You can have the leg."); + addFortune("Protective eyewear is a must!"); + addFortune("It's all in the wristwatch."); + addFortune("Endermen in the UCB!"); + addFortune("Endermen can move TNT. I'm serious."); + addFortune("Aww, you got blood all over my new sword!"); + addFortune("The human pancreas can take only so many twinkies."); + addFortune("Humus is something you eat when you want your innards to cry."); + addFortune("By Mennen"); + addFortune("Put me back in!"); + addFortune("...I got nothin'."); + addFortune("We're out of milk."); + addFortune("Always edit-out the derps."); + addFortune("I want a lawyer."); + addFortune("Bring me a shrubbery!"); + addFortune("It's bigger on the inside."); + addFortune("That's what she said."); + addFortune("Have you heard the one about the Rabbi and the Priest? Oh I forgot, you're deaf."); + addFortune("There are worse appendages to get caught sticking inside the cookie jar."); + addFortune("Ever have the feeling you're being watched? That's me!"); + addFortune("He who handles his NullPointerExceptions is a wise man indeed."); + addFortune("Taking candy from a baby often prevents choking."); + addFortune("Texting while driving is a potent form of natural-selection."); + addFortune("The secret to a good marriage is matching tattoos."); + addFortune("A sucker is born every minute, however an idiot is born every two seconds."); + addFortune("Error in Thread Main: ExceptionNotCaughtException: DartCraft.java:32"); + addFortune("I'll tear YOUR stub!"); + addFortune("Daydreaming is free, cookies are not."); + addFortune("PINGAS!"); + addFortune("The run is dead."); + } + +} diff --git a/src/main/resources/assets/dartcraft/engineGui.png b/src/main/resources/assets/dartcraft/engineGui.png new file mode 100644 index 0000000000000000000000000000000000000000..7e457eb5a78e91eeb0681816f38424ddd3f94aec GIT binary patch literal 23378 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

RMK{Bm_^JKroKv#2q*F|49} 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/dartcraft/forceEngine.png b/src/main/resources/assets/dartcraft/forceEngine.png new file mode 100644 index 0000000000000000000000000000000000000000..522c0a64a99693ebf61f44dc5589112a21c22c50 GIT binary patch literal 5375 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/dartcraft/textures/blocks/liquidForceMoving.png b/src/main/resources/assets/dartcraft/textures/blocks/liquidForceMoving.png new file mode 100644 index 0000000000000000000000000000000000000000..663d357b4756e8d02a3a338214e048a8a1242ba2 GIT binary patch literal 12733 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 |@90(y4Ux<>f@+L;1v&*BaI!d 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 NR1`H7%H=GB{vU&pE&u=k literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/dartcraft/textures/blocks/liquidForceMoving.png.mcmeta b/src/main/resources/assets/dartcraft/textures/blocks/liquidForceMoving.png.mcmeta new file mode 100644 index 0000000..7e77c64 --- /dev/null +++ b/src/main/resources/assets/dartcraft/textures/blocks/liquidForceMoving.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/dartcraft/textures/blocks/liquidForceStill.png b/src/main/resources/assets/dartcraft/textures/blocks/liquidForceStill.png new file mode 100644 index 0000000000000000000000000000000000000000..35964acf8c1d5d3b594c9f468fdae012d2f04bc6 GIT binary patch literal 14006 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/dartcraft/textures/blocks/liquidForceStill.png.mcmeta b/src/main/resources/assets/dartcraft/textures/blocks/liquidForceStill.png.mcmeta new file mode 100644 index 0000000..88b68da --- /dev/null +++ b/src/main/resources/assets/dartcraft/textures/blocks/liquidForceStill.png.mcmeta @@ -0,0 +1,45 @@ +{ + "animation": { + "frametime": 3, + "frames": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 10, + 9, + 8, + 7, + 6, + 5, + 4, + 3, + 2, + 1 + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/dartcraft/textures/blocks/milk.png b/src/main/resources/assets/dartcraft/textures/blocks/milk.png new file mode 100644 index 0000000000000000000000000000000000000000..f55d68a4abd24705b97585e9d0ed063b35a37032 GIT binary patch literal 8200 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