commit e13a214549236cebd2568aec5a3ceeeee7202e9e Author: Calclavia Date: Sun Oct 28 13:25:56 2012 +0800 Initial 1.4.2 and UE 1.0 update diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..412eeda7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..097d6362 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +/bin/* +/conf/* +/docs/* +/eclipse/* +/forge/* +/jars/* +/lib/* +/logs/* +/modsrc/* +/reobf/* +/runtime/* +/temp/* +CHANGELOG +LICENSE.txt +*.bat +*.sh + +/src/minecraft/* +/src/minecraft_server/* +/src/common/* +/builds/ + +!/src/*/assemblyline/ +!/src/*/dan200/ +!/src/*/buildcraft/ +!/src/*/universalelectricity/ +!/Include Resources.bat +!/mcmod.info + +!/resources/* +!/modversion.txt +!/publish.bat +!/README \ No newline at end of file diff --git a/Include Resources.bat b/Include Resources.bat new file mode 100644 index 00000000..0d85a808 --- /dev/null +++ b/Include Resources.bat @@ -0,0 +1,4 @@ +@echo off +cd resources +"..\..\7za.exe" a "..\jars\bin\minecraft.jar" "*" +pause \ No newline at end of file diff --git a/mcmod.info b/mcmod.info new file mode 100644 index 00000000..6d91f15e --- /dev/null +++ b/mcmod.info @@ -0,0 +1,22 @@ +[ +{ + "modid": "AssemblyLine", + "name": "Assembly Line", + "description": "A mod bringing a realistic conveyor belt transporting system to Minecraft.", + "version": "0.1.0", + "mcversion": "1.4.2", + "url": "http://calclavia.com/universalelectricity/?m=18", + "updateUrl": "http://calclavia.com/universalelectricity/?m=18", + "authors": [ + "Calclavia", + "Darkguardsman" + ], + "credits": "Authored by Calclavia and Darkguardsman", + "logoFile": "", + "screenshots": [ + ], + "parent":"", + "dependencies": [ + ] +} +] \ No newline at end of file diff --git a/modversion.txt b/modversion.txt new file mode 100644 index 00000000..99d85ecd --- /dev/null +++ b/modversion.txt @@ -0,0 +1 @@ +0.0.6 \ No newline at end of file diff --git a/src/common/assemblyline/ALProxy.java b/src/common/assemblyline/ALProxy.java new file mode 100644 index 00000000..c12f04c8 --- /dev/null +++ b/src/common/assemblyline/ALProxy.java @@ -0,0 +1,57 @@ +package assemblyline; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import asmline.GUIEjectorSettings; +import assemblyline.interaction.ContainerEjector; +import assemblyline.interaction.TileEntityEjector; +import cpw.mods.fml.common.network.IGuiHandler; + +public class ALProxy implements IGuiHandler +{ + + public void preInit() + { + + } + public void init() + { + + } + public void postInit() + { + + } + @Override + public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) + { + TileEntity tileEntity = world.getBlockTileEntity(x, y, z); + + if (tileEntity != null) + { + switch(ID) + { + case 0: return new GUIEjectorSettings(player.inventory, ((TileEntityEjector)tileEntity)); + } + } + + return null; + } + + @Override + public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) + { + TileEntity tileEntity = world.getBlockTileEntity(x, y, z); + + if (tileEntity != null) + { + switch(ID) + { + case 0: return new ContainerEjector(player.inventory, ((TileEntityEjector)tileEntity)); + } + } + + return null; + } +} diff --git a/src/common/assemblyline/AssembleLine.java b/src/common/assemblyline/AssembleLine.java new file mode 100644 index 00000000..40c50dbc --- /dev/null +++ b/src/common/assemblyline/AssembleLine.java @@ -0,0 +1,100 @@ +package assemblyline; + +import java.io.File; + +import net.minecraft.src.Block; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import net.minecraftforge.common.Configuration; +import net.minecraftforge.oredict.ShapedOreRecipe; +import net.minecraftforge.oredict.ShapelessOreRecipe; +import universalelectricity.prefab.network.PacketManager; +import assemblyline.belts.BlockConveyorBelt; +import assemblyline.belts.TileEntityConveyorBelt; +import assemblyline.interaction.BlockInteraction; +import assemblyline.interaction.ItemMachine; +import assemblyline.interaction.TileEntityEjector; +import assemblyline.interaction.TileEntityMachineInput; +import cpw.mods.fml.common.Mod; +import cpw.mods.fml.common.Mod.Init; +import cpw.mods.fml.common.Mod.PostInit; +import cpw.mods.fml.common.Mod.PreInit; +import cpw.mods.fml.common.SidedProxy; +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLPostInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.network.NetworkMod; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.common.registry.LanguageRegistry; + +@Mod(modid = "asmLine", name = "Assemble Line", version = "V2.3", dependencies = "after:UniversalElectricity") +@NetworkMod(channels = +{ "asmLine" }, clientSideRequired = true, serverSideRequired = false, packetHandler = PacketManager.class) +public class AssembleLine +{ + @SidedProxy(clientSide = "asmline.asmClientProxy", serverSide = "asmline.asmProxy") + public static ALProxy proxy; + public static AssembleLine instance; + public static final Configuration config = new Configuration(new File(cpw.mods.fml.common.Loader.instance().getConfigDir(), "UniversalElectricity/ConveyorBelts.cfg")); + public static int machineID = configurationProperties(); + public static int machine2ID; + public static int beltBlockID; + public static boolean animationOn; + public static final String TEXTURE_PATH = "/textures"; + public static final Block blockConveyorBelt = new BlockConveyorBelt(beltBlockID); + public static final Block blockMachine = new BlockInteraction(machineID); + + public static int configurationProperties() + { + config.load(); + beltBlockID = Integer.parseInt(config.getBlock(Configuration.CATEGORY_BLOCK, "BeltBlockID", 3003).value); + machineID = Integer.parseInt(config.getBlock(Configuration.CATEGORY_BLOCK, "MachineID", 3005).value); + animationOn = Boolean.parseBoolean(config.get(Configuration.CATEGORY_GENERAL, "BeltAnimationOn", true).value); + config.save(); + return machineID; + } + + @PreInit + public void preInit(FMLPreInitializationEvent event) + { + instance = this; + NetworkRegistry.instance().registerGuiHandler(this, this.proxy); + GameRegistry.registerBlock(blockConveyorBelt); + GameRegistry.registerBlock(blockMachine, ItemMachine.class); + proxy.preInit(); + } + + @Init + public void load(FMLInitializationEvent evt) + { + GameRegistry.registerTileEntity(TileEntityConveyorBelt.class, "belt"); + GameRegistry.registerTileEntity(TileEntityEjector.class, "ejector"); + GameRegistry.registerTileEntity(TileEntityMachineInput.class, "scop"); + proxy.init(); + // Names + LanguageRegistry.addName(new ItemStack(blockConveyorBelt, 1), "Coneveyor Belt"); + LanguageRegistry.addName(new ItemStack(blockMachine, 1, 0), "Ejector"); + LanguageRegistry.addName(new ItemStack(blockMachine, 1, 4), "MachineInput"); + LanguageRegistry.addName(new ItemStack(blockMachine, 1, 8), "FutureBlock"); + LanguageRegistry.addName(new ItemStack(blockMachine, 1, 12), "FutureBlock"); + } + + @PostInit + public void postInit(FMLPostInitializationEvent event) + { + //Conveyor Belt + GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(blockConveyorBelt), new Object[] + { "III", "MCM", 'I', Item.ingotIron, 'M', "motor", 'C', "basicCircuit" })); + + //Rejector + GameRegistry.addRecipe(new ItemStack(blockMachine, 1, 0), new Object[] + { "WPW", "@R@", '@', "plateSteel", 'R', Item.redstone, 'P', Block.pistonBase, 'C', "basicCircuit", 'W', "copperWire"}); + + //Retriever + GameRegistry.addRecipe(new ShapelessOreRecipe(new ItemStack(blockMachine, 1, 4), new Object[] + { Block.dispenser, "basicCircuit"})); + proxy.postInit(); + } + +} \ No newline at end of file diff --git a/src/common/assemblyline/TileEntityBase.java b/src/common/assemblyline/TileEntityBase.java new file mode 100644 index 00000000..42e68049 --- /dev/null +++ b/src/common/assemblyline/TileEntityBase.java @@ -0,0 +1,278 @@ +package assemblyline; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.IInventory; +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.NBTTagList; +import universalelectricity.prefab.TileEntityAdvanced; +import universalelectricity.prefab.network.IPacketReceiver; + +public abstract class TileEntityBase extends TileEntityAdvanced implements IPacketReceiver, IInventory +{ + /** + * The items this container contains. + */ + protected ItemStack[] containingItems = new ItemStack[this.getSizeInventory()]; + + /** + * The amount of players using this tile entity. + */ + protected int playerUsing = 0; + + /** + * Is this tile entity locked? + */ + protected boolean locked = false; + + /** + * The owner of this tile entity. + */ + protected String owner = ""; + + /* + * { if (count++ >= + * 10) { count = 0; if (!worldObj.isRemote && + * this.sendDataA() != null) { Packet packet = + * PacketManager.getPacket("asmLine", this, + * this.buildData(1)); + * PacketManager.sendPacketToClients(packet, + * worldObj, Vector3.get(this), 40); } if + * (!worldObj.isRemote && this.sendDataG() != + * null && this.isOpen) { Packet packet = + * PacketManager.getPacket("asmLine", this, + * this.buildData(0)); + * PacketManager.sendPacketToClients(packet, + * worldObj, Vector3.get(this), 10); } } if + * (ticks++ % tickRate() >= 0 && + * !isDisabled()) { this.tickedUpdate(); } } + */ + + /** + * Inventory functions. + */ + @Override + public ItemStack getStackInSlot(int par1) + { + return this.containingItems[par1]; + } + + @Override + public ItemStack decrStackSize(int par1, int par2) + { + if (this.containingItems[par1] != null) + { + ItemStack var3; + + if (this.containingItems[par1].stackSize <= par2) + { + var3 = this.containingItems[par1]; + this.containingItems[par1] = null; + return var3; + } + else + { + var3 = this.containingItems[par1].splitStack(par2); + + if (this.containingItems[par1].stackSize == 0) + { + this.containingItems[par1] = null; + } + + return var3; + } + } + else + { + return null; + } + } + + @Override + public ItemStack getStackInSlotOnClosing(int par1) + { + if (this.containingItems[par1] != null) + { + ItemStack var2 = this.containingItems[par1]; + this.containingItems[par1] = null; + return var2; + } + else + { + return null; + } + } + + @Override + public void setInventorySlotContents(int par1, ItemStack par2ItemStack) + { + this.containingItems[par1] = par2ItemStack; + + if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) + { + par2ItemStack.stackSize = this.getInventoryStackLimit(); + } + } + + @Override + public int getInventoryStackLimit() + { + return 64; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) + { + return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : par1EntityPlayer.getDistanceSq(this.xCoord + 0.5D, this.yCoord + 0.5D, this.zCoord + 0.5D) <= 64.0D; + } + + @Override + public void openChest() + { + this.playerUsing++; + } + + @Override + public void closeChest() + { + this.playerUsing--; + } + + /** + * NBT Data + */ + @Override + public void readFromNBT(NBTTagCompound nbt) + { + super.readFromNBT(nbt); + this.locked = nbt.getBoolean("locked"); + this.owner = nbt.getString("Owner"); + + NBTTagList var2 = nbt.getTagList("Items"); + this.containingItems = new ItemStack[this.getSizeInventory()]; + + for (int var3 = 0; var3 < var2.tagCount(); ++var3) + { + NBTTagCompound var4 = (NBTTagCompound) var2.tagAt(var3); + byte var5 = var4.getByte("Slot"); + + if (var5 >= 0 && var5 < this.containingItems.length) + { + this.containingItems[var5] = ItemStack.loadItemStackFromNBT(var4); + } + } + } + + /** + * Writes a tile entity to NBT. + */ + @Override + public void writeToNBT(NBTTagCompound nbt) + { + super.writeToNBT(nbt); + nbt.setBoolean("locked", this.locked); + nbt.setString("Owner", this.owner); + + NBTTagList var2 = new NBTTagList(); + for (int var3 = 0; var3 < this.containingItems.length; ++var3) + { + if (this.containingItems[var3] != null) + { + NBTTagCompound var4 = new NBTTagCompound(); + var4.setByte("Slot", (byte) var3); + this.containingItems[var3].writeToNBT(var4); + var2.appendTag(var4); + } + } + nbt.setTag("Items", var2); + } +/* + @Override + public void handlePacketData(NetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream) + { + if (worldObj.isRemote) + { + try + { + int ID = dataStream.readInt(); + if (ID == 0) + { + this.guiPacket(network, packetType, packet, player, dataStream); + } + else if (ID == 1) + { + this.animationPacket(network, packetType, packet, player, dataStream); + } + else + { + + } + + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } + + /** + * Used to read GUI only data sent to the TE + + public abstract void guiPacket(NetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream); + + /** + * Used to read animation data for things that + * can be seen on a TE + + public abstract void animationPacket(NetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream); + + /** + * Used to read data for none animation or gui + * server sent packets + * + public abstract void otherPacket(NetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream); + + public Object[] buildData(int packetID) + { + Object[] data = new Object[1]; + + if (packetID == 0) + { + data = new Object[this.sendDataG().length + 1]; + data[0] = packetID; + for (int i = 0; i < this.sendDataG().length; i++) + { + data[i + 1] = this.sendDataG()[i]; + } + } + else if (packetID == 1) + { + data = new Object[this.sendDataA().length + 1]; + data[0] = packetID; + for (int i = 0; i < this.sendDataA().length; i++) + { + data[i + 1] = this.sendDataA()[i]; + } + } + return data; + } + + /** + * Array of data too be sent for animation + * updates + * + * @return + * + public abstract Object[] sendDataA(); + + /** + * Array of data too be sent if the TE's GUI + * is open at the time + * + * @return + * + public abstract Object[] sendDataG(); + + */ +} diff --git a/src/common/assemblyline/belts/BlockConveyorBelt.java b/src/common/assemblyline/belts/BlockConveyorBelt.java new file mode 100644 index 00000000..7b89adb1 --- /dev/null +++ b/src/common/assemblyline/belts/BlockConveyorBelt.java @@ -0,0 +1,88 @@ +package assemblyline.belts; + +import net.minecraft.src.CreativeTabs; +import net.minecraft.src.EntityLiving; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.Material; +import net.minecraft.src.MathHelper; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import universalelectricity.prefab.BlockMachine; +import asmline.beltRenders.BeltRenderHelper; + +/** + * The block for the actual conveyor! + * + * @Oldauthors Calclavia,Elusivehawk + * @author DarkGuardsman + */ +public class BlockConveyorBelt extends BlockMachine +{ + public BlockConveyorBelt(int id) + { + super("Conveyor Belt", id, Material.wood); + this.setBlockBounds(0, 0, 0, 1, 0.3f, 1); + this.setTextureFile("/textures/items.png"); + this.blockIndexInTexture = 0; + this.setCreativeTab(CreativeTabs.tabRedstone); + } + @Override + public void onBlockPlacedBy(World par1World, int x, int y, int z, EntityLiving par5EntityLiving) + { + int angle = MathHelper.floor_double((par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3; + par1World.setBlockAndMetadataWithNotify(x, y, z, this.blockID, angle); + } + + @Override + public boolean onUseWrench(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + int metadata = par1World.getBlockMetadata(x, y, z); + + if (metadata >= 0 && metadata < 4) + { + if (metadata == 3) + { + par1World.setBlockAndMetadataWithNotify(x, y, z, this.blockID, 0); + return true; + } + else + { + par1World.setBlockAndMetadataWithNotify(x, y, z, this.blockID, metadata + 1); + return true; + } + } + + return true; + } + + /** + * Returns the TileEntity used by this block. + */ + @Override + public TileEntity createNewTileEntity(World var1,int meta) + { + if(meta >=0 && meta < 4) + { + return new TileEntityConveyorBelt(); + } + return null; + } + + @Override + public int getRenderType() + { + return BeltRenderHelper.blockRenderId; + } + + @Override + public boolean isOpaqueCube() + { + return false; + } + @Override + public boolean renderAsNormalBlock() + { + return false; + } + +} diff --git a/src/common/assemblyline/belts/TileEntityConveyorBelt.java b/src/common/assemblyline/belts/TileEntityConveyorBelt.java new file mode 100644 index 00000000..bf66539e --- /dev/null +++ b/src/common/assemblyline/belts/TileEntityConveyorBelt.java @@ -0,0 +1,334 @@ +package assemblyline.belts; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.src.AxisAlignedBB; +import net.minecraft.src.Entity; +import net.minecraft.src.EntityItem; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.INetworkManager; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.Packet; +import net.minecraft.src.Packet250CustomPayload; +import net.minecraft.src.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.core.Vector3; +import universalelectricity.implement.IConductor; +import universalelectricity.prefab.TileEntityElectricityReceiver; +import universalelectricity.prefab.network.IPacketReceiver; +import universalelectricity.prefab.network.PacketManager; +import assemblyline.AssembleLine; + +import com.google.common.io.ByteArrayDataInput; + +public class TileEntityConveyorBelt extends TileEntityElectricityReceiver implements IPacketReceiver +{ + public double electricityStored = 0; + public final double electricityRequired = 0.1f; + public final double energyMax = 10; + private float speed = -0.05F; + public float wheelRotation = 0; + public boolean running = false; + public boolean flip = false; + public TileEntityConveyorBelt[] adjBelts = + { null, null, null, null }; + + public int clearCount = 0; + public int range = 0; + public boolean connected = false; + public List entityIgnoreList = new ArrayList(); + + // Checks Adjacent belt to see if there + // powered. Reduces need for wire per belt + public boolean powerNeighbor() + { + for (int n = 2; n < 6; n++) + { + ForgeDirection d = ForgeDirection.getOrientation(n); + TileEntity ent = worldObj.getBlockTileEntity(xCoord - d.offsetX, yCoord, zCoord - d.offsetZ); + if (ent instanceof TileEntityConveyorBelt) + { + adjBelts[n - 2] = (TileEntityConveyorBelt) ent; + } + else + { + adjBelts[n - 2] = null; + } + } + int rr = 0; + for (int b = 0; b < 4; b++) + { + if (adjBelts[b] instanceof TileEntityConveyorBelt) + { + TileEntityConveyorBelt belt = (TileEntityConveyorBelt) adjBelts[b]; + if (belt.range > rr) + { + rr = belt.getRange(); + } + } + } + this.range = rr - 1; + return false; + } + + public int getRange() + { + return this.range; + } + + @Override + public void updateEntity() + { + super.updateEntity(); + + if (this.ticks % 10 == 0) + { + if (worldObj.getBlockTileEntity(xCoord, yCoord - 1, zCoord) instanceof IConductor) + { + this.connected = true; + } + else + { + this.connected = false; + } + + if (this.electricityStored >= this.electricityRequired) + { + this.electricityStored = Math.max(this.electricityStored - this.electricityRequired, 0); + this.range = 20; + } + else + { + this.range = 0; + } + if (!this.connected) + { + powerNeighbor(); + } + if (this.range > 0) + { + this.running = true; + } + else + { + this.running = false; + } + + if (!worldObj.isRemote) + { + Packet packet = PacketManager.getPacket("asmLine", this, new Object[] + { running, range }); + PacketManager.sendPacketToClients(packet, worldObj, new Vector3(xCoord, yCoord, zCoord), 40); + + } + + } + if (this.running) + { + AxisAlignedBB bounds = AxisAlignedBB.getBoundingBox(this.xCoord, this.yCoord, this.zCoord, this.xCoord + 1, this.yCoord + 1, this.zCoord + 1); + try + { + List entityOnTop = worldObj.getEntitiesWithinAABB(Entity.class, bounds); + + for (Entity entity : entityOnTop) + { + int direction = worldObj.getBlockMetadata(xCoord, yCoord, zCoord); + if (!this.entityIgnoreList.contains(entity)) + { + if (direction == 0) + { + entity.motionZ -= 1 * this.speed; + } + if (direction == 1) + { + entity.motionX += 1 * this.speed; + } + if (direction == 2) + { + entity.motionZ += 1 * this.speed; + } + if (direction == 3) + { + entity.motionX -= 1 * this.speed; + } + } + if (this.clearCount++ >= 4) + { + // clear the temp ignore + // list every 2 second + this.entityIgnoreList.clear(); + } + if (entity instanceof EntityItem) + { + EntityItem entityItem = (EntityItem) entity; + // Make sure the item + // doesn't decay/disappear + if (entityItem.age >= 1000) + { + entityItem.age = 0; + } + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + + if (AssembleLine.animationOn) + { + if (flip == true) + { + flip = false; + } + else + { + flip = true; + } + this.wheelRotation -= this.speed; + } + } + } + + @Override + public double wattRequest() + { + return energyMax - electricityStored; + } + + @Override + public boolean canReceiveFromSide(ForgeDirection side) + { + return side == ForgeDirection.DOWN; + } + + public int getBeltDirection() + { + int meta = worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord); + if (meta >= 0 && meta < 4) + { + switch (meta) + { + case 0: + return 2; + case 1: + return 5; + case 2: + return 3; + case 3: + return 4; + } + } + return 0; + } + + public boolean middleBelt() + { + + ForgeDirection front = ForgeDirection.getOrientation(getBeltDirection()); + ForgeDirection back = ForgeDirection.getOrientation(getBeltDirection()).getOpposite(); + TileEntity fBelt = worldObj.getBlockTileEntity(xCoord + front.offsetX, yCoord + front.offsetY, zCoord + front.offsetZ); + TileEntity BBelt = worldObj.getBlockTileEntity(xCoord + back.offsetX, yCoord + back.offsetY, zCoord + back.offsetZ); + if (fBelt instanceof TileEntityConveyorBelt && BBelt instanceof TileEntityConveyorBelt) + { + int fD = ((TileEntityConveyorBelt) fBelt).getBeltDirection(); + int BD = ((TileEntityConveyorBelt) BBelt).getBeltDirection(); + int TD = this.getBeltDirection(); + if (fD == TD && BD == TD) { return true; } + } + return false; + } + + public boolean FrontCap() + { + + ForgeDirection front = ForgeDirection.getOrientation(getBeltDirection()); + ForgeDirection back = ForgeDirection.getOrientation(getBeltDirection()).getOpposite(); + TileEntity fBelt = worldObj.getBlockTileEntity(xCoord + front.offsetX, yCoord + front.offsetY, zCoord + front.offsetZ); + TileEntity BBelt = worldObj.getBlockTileEntity(xCoord + back.offsetX, yCoord + back.offsetY, zCoord + back.offsetZ); + if (fBelt instanceof TileEntityConveyorBelt) + { + int fD = ((TileEntityConveyorBelt) fBelt).getBeltDirection(); + int TD = this.getBeltDirection(); + if (fD == TD) { return true; } + } + return false; + } + + public boolean BackCap() + { + + ForgeDirection front = ForgeDirection.getOrientation(getBeltDirection()); + ForgeDirection back = ForgeDirection.getOrientation(getBeltDirection()).getOpposite(); + TileEntity fBelt = worldObj.getBlockTileEntity(xCoord + front.offsetX, yCoord + front.offsetY, zCoord + front.offsetZ); + TileEntity BBelt = worldObj.getBlockTileEntity(xCoord + back.offsetX, yCoord + back.offsetY, zCoord + back.offsetZ); + if (BBelt instanceof TileEntityConveyorBelt) + { + int BD = ((TileEntityConveyorBelt) BBelt).getBeltDirection(); + int TD = this.getBeltDirection(); + if (BD == TD) { return true; } + } + return false; + } + + @Override + public void handlePacketData(INetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream) + { + if (worldObj.isRemote) + { + try + { + this.running = dataStream.readBoolean(); + this.range = dataStream.readInt(); + + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + } + + @Override + public void onReceive(TileEntity sender, double amps, double voltage, ForgeDirection side) + { + this.electricityStored += (amps * voltage); + + } + + /** + * Used to tell the belt not to apply velocity + * to some Entity in case they are being + * handled by another block. For example + * ejector + * + * @param entity + */ + public void ignore(Entity entity) + { + if (!this.entityIgnoreList.contains(entity)) + { + this.entityIgnoreList.add(entity); + } + + } + + @Override + public void readFromNBT(NBTTagCompound nbt) + { + super.readFromNBT(nbt); + this.electricityStored = nbt.getDouble("energy"); + } + + /** + * Writes a tile entity to NBT. + */ + @Override + public void writeToNBT(NBTTagCompound nbt) + { + super.writeToNBT(nbt); + nbt.setDouble("energy", this.electricityStored); + } +} diff --git a/src/common/assemblyline/crafting/BlockCrafter.java b/src/common/assemblyline/crafting/BlockCrafter.java new file mode 100644 index 00000000..4bf75690 --- /dev/null +++ b/src/common/assemblyline/crafting/BlockCrafter.java @@ -0,0 +1,45 @@ +package assemblyline.crafting; + +import net.minecraft.src.BlockContainer; +import net.minecraft.src.CreativeTabs; +import net.minecraft.src.Material; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; + +public class BlockCrafter extends BlockContainer +{ + protected BlockCrafter(int par1) + { + super(par1, Material.iron); + this.setResistance(5.0f); + this.setHardness(5.0f); + this.setCreativeTab(CreativeTabs.tabTools); + } + + @Override + public TileEntity createNewTileEntity(World var1) { + + return null; + } + @Override + public TileEntity createNewTileEntity(World var1, int meta) { + if(meta >= 0 && meta < 4) + { + return new TileEntityAutoCrafter(); + } + if(meta >= 4 && meta < 8) + { + return new TileEntityCraftingArm(); + } + if(meta >= 8 && meta < 12) + { + + } + if(meta >= 12 && meta < 16) + { + + } + return null; + } + +} diff --git a/src/common/assemblyline/crafting/EntityCraftingArm.java b/src/common/assemblyline/crafting/EntityCraftingArm.java new file mode 100644 index 00000000..4328b455 --- /dev/null +++ b/src/common/assemblyline/crafting/EntityCraftingArm.java @@ -0,0 +1,30 @@ +package assemblyline.crafting; + +import net.minecraft.src.Entity; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.World; + +public class EntityCraftingArm extends Entity { + + public EntityCraftingArm(World par1World) { + super(par1World); + } + + @Override + protected void entityInit() + { + + } + + @Override + protected void readEntityFromNBT(NBTTagCompound var1) { + // TODO Auto-generated method stub + + } + + @Override + protected void writeEntityToNBT(NBTTagCompound var1) { + // TODO Auto-generated method stub + + } +} diff --git a/src/common/assemblyline/crafting/TileEntityAutoCrafter.java b/src/common/assemblyline/crafting/TileEntityAutoCrafter.java new file mode 100644 index 00000000..996c5c67 --- /dev/null +++ b/src/common/assemblyline/crafting/TileEntityAutoCrafter.java @@ -0,0 +1,46 @@ +package assemblyline.crafting; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.INetworkManager; +import net.minecraft.src.ItemStack; +import net.minecraft.src.Packet250CustomPayload; +import net.minecraftforge.common.ForgeDirection; +import net.minecraftforge.common.ISidedInventory; +import universalelectricity.prefab.TileEntityAdvanced; + +import assemblyline.TileEntityBase; + +import com.google.common.io.ByteArrayDataInput; + +public class TileEntityAutoCrafter extends TileEntityBase implements ISidedInventory +{ + @Override + public String getInvName() + { + return "Auto Crafter"; + } + + @Override + public int getSizeInventory() + { + return 10; + } + + @Override + public void handlePacketData(INetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream) + { + + } + + @Override + public int getStartInventorySide(ForgeDirection side) + { + return 0; + } + + @Override + public int getSizeInventorySide(ForgeDirection side) + { + return 0; + } +} diff --git a/src/common/assemblyline/crafting/TileEntityCraftingArm.java b/src/common/assemblyline/crafting/TileEntityCraftingArm.java new file mode 100644 index 00000000..1bb10ab2 --- /dev/null +++ b/src/common/assemblyline/crafting/TileEntityCraftingArm.java @@ -0,0 +1,7 @@ +package assemblyline.crafting; + +import net.minecraft.src.TileEntity; + +public class TileEntityCraftingArm extends TileEntity { + +} diff --git a/src/common/assemblyline/interaction/BlockInteraction.java b/src/common/assemblyline/interaction/BlockInteraction.java new file mode 100644 index 00000000..15bbdc10 --- /dev/null +++ b/src/common/assemblyline/interaction/BlockInteraction.java @@ -0,0 +1,146 @@ +package assemblyline.interaction; + +import net.minecraft.src.CreativeTabs; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.Material; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import universalelectricity.prefab.BlockMachine; +import asmline.beltRenders.BeltRenderHelper; +import assemblyline.AssembleLine; + +public class BlockInteraction extends BlockMachine +{ + public BlockInteraction(int id) + { + super("Machine", id, Material.iron); + this.setCreativeTab(CreativeTabs.tabRedstone); + } + + public int damageDropped(int metadata) + { + if (metadata >= 0 && metadata < 4) { return 0; } + if (metadata >= 4 && metadata < 8) { return 4; } + if (metadata >= 8 && metadata < 12) { return 8; } + if (metadata >= 12 && metadata < 16) { return 12; } + return 0; + } + + public boolean onSneakUseWrench(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + if (!par1World.isRemote) + { + par5EntityPlayer.openGui(AssembleLine.instance, 0, par1World, x, y, z); + return true; + } + return true; + } + + @Override + public boolean onUseWrench(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + int metadata = par1World.getBlockMetadata(x, y, z); + + if (metadata == 3) + { + par1World.setBlockAndMetadataWithNotify(x, y, z, this.blockID, 0); + return true; + } + else if (metadata == 7) + { + par1World.setBlockAndMetadataWithNotify(x, y, z, this.blockID, 4); + return true; + } + else if (metadata == 11) + { + par1World.setBlockAndMetadataWithNotify(x, y, z, this.blockID, 8); + return true; + } + else if (metadata == 15) + { + par1World.setBlockAndMetadataWithNotify(x, y, z, this.blockID, 12); + return true; + } + else + { + par1World.setBlockAndMetadataWithNotify(x, y, z, this.blockID, metadata + 1); + return true; + } + } + + /** + * gets the correct facing direction from meta + * data + * + * @param meta + * @return facing direction(int) + */ + public byte getDirection(int meta) + { + + switch (meta) + { + case 0: + return 2; + case 1: + return 5; + case 2: + return 3; + case 3: + return 4; + case 4: + return 2; + case 5: + return 5; + case 6: + return 3; + case 7: + return 4; + case 8: + return 2; + case 9: + return 5; + case 10: + return 3; + case 11: + return 4; + case 12: + return 2; + case 13: + return 5; + case 14: + return 3; + case 15: + return 4; + } + return 0; + } + + @Override + public TileEntity createNewTileEntity(World var1, int metadata) + { + if (metadata >= 0 && metadata < 4) { return new TileEntityEjector(); } + if (metadata >= 4 && metadata < 8) { return new TileEntityMachineInput(); } + if (metadata >= 8 && metadata < 12) { return null; } + if (metadata >= 12 && metadata < 16) { return null; } + return null; + } + + @Override + public int getRenderType() + { + return BeltRenderHelper.blockRenderId; + } + + @Override + public boolean isOpaqueCube() + { + return false; + } + + @Override + public boolean renderAsNormalBlock() + { + return false; + } +} diff --git a/src/common/assemblyline/interaction/ContainerEjector.java b/src/common/assemblyline/interaction/ContainerEjector.java new file mode 100644 index 00000000..7c3c6b6c --- /dev/null +++ b/src/common/assemblyline/interaction/ContainerEjector.java @@ -0,0 +1,95 @@ +package assemblyline.interaction; + +import net.minecraft.src.Container; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.InventoryPlayer; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import net.minecraft.src.Slot; + +public class ContainerEjector extends Container +{ + private TileEntityEjector tileEntity; + + public ContainerEjector(InventoryPlayer par1InventoryPlayer, TileEntityEjector tileEntity) + { + this.tileEntity = tileEntity; + for(int i = 0; i < 4; i++) + { + this.addSlotToContainer(new Slot(tileEntity, 0+i, 33 +i*18, 34)); + } + int var3; + + for (var3 = 0; var3 < 3; ++var3) + { + for (int var4 = 0; var4 < 9; ++var4) + { + this.addSlotToContainer(new Slot(par1InventoryPlayer, var4 + var3 * 9 + 9, 8 + var4 * 18, 84 + var3 * 18)); + } + } + + for (var3 = 0; var3 < 9; ++var3) + { + this.addSlotToContainer(new Slot(par1InventoryPlayer, var3, 8 + var3 * 18, 142)); + } + } + + @Override + public boolean canInteractWith(EntityPlayer par1EntityPlayer) + { + return this.tileEntity.isUseableByPlayer(par1EntityPlayer); + } + + /** + * Called to transfer a stack from one inventory to the other eg. when shift clicking. + */ + @Override + public ItemStack transferStackInSlot(int par1) + { + ItemStack var2 = null; + Slot var3 = (Slot)this.inventorySlots.get(par1); + + if (var3 != null && var3.getHasStack()) + { + ItemStack var4 = var3.getStack(); + var2 = var4.copy(); + + if (par1 != 0) + { + if (var4.itemID == Item.coal.shiftedIndex) + { + if (!this.mergeItemStack(var4, 0, 1, false)) + { + return null; + } + } + else if (par1 >= 30 && par1 < 37 && !this.mergeItemStack(var4, 3, 30, false)) + { + return null; + } + } + else if (!this.mergeItemStack(var4, 3, 37, false)) + { + return null; + } + + if (var4.stackSize == 0) + { + var3.putStack((ItemStack)null); + } + else + { + var3.onSlotChanged(); + } + + if (var4.stackSize == var2.stackSize) + { + return null; + } + + var3.onPickupFromSlot(var4); + } + + return var2; + } +} diff --git a/src/common/assemblyline/interaction/ItemMachine.java b/src/common/assemblyline/interaction/ItemMachine.java new file mode 100644 index 00000000..cead536c --- /dev/null +++ b/src/common/assemblyline/interaction/ItemMachine.java @@ -0,0 +1,83 @@ +package assemblyline.interaction; + +import java.util.List; + +import net.minecraft.src.Block; +import net.minecraft.src.CreativeTabs; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.ItemBlock; +import net.minecraft.src.ItemStack; +import net.minecraft.src.MathHelper; +import net.minecraft.src.World; +import assemblyline.AssembleLine; + +public class ItemMachine extends ItemBlock { + + public ItemMachine(int par1) { + super(par1); + this.setHasSubtypes(true); + this.setCreativeTab(CreativeTabs.tabRedstone); + } + private String[] names = new String[] {"Ejector", "ItemScooper", "FB","FB"}; + int blockID = AssembleLine.machineID; + public void getSubItems(int par1, CreativeTabs par2CreativeTabs, List par3List) + { + par3List.add(new ItemStack(AssembleLine.blockMachine,1,0)); + par3List.add(new ItemStack(AssembleLine.blockMachine,1,4)); + //par3List.add(new ItemStack(AssembleLine.blockMachine,1,8)); + //par3List.add(new ItemStack(AssembleLine.blockMachine,1,12)); + } + public String getItemNameIS(ItemStack itemstack) + { + int meta = itemstack.getItemDamage(); + switch(meta) + { + case 0: return names[0]; + case 4: return names[1]; + case 8: return names[2]; + case 12: return names[3]; + } + return "FB"; + } + + @Override + public int getIconFromDamage(int i) + { + switch(i) + { + case 0:return 1; + case 4:return 2; + case 8:return 3; + case 12:return 4; + } + return this.iconIndex + i; + } + public int getMetadata(int par1) + { + return 0; + } + @Override + public int getBlockID() + { + return AssembleLine.machineID; + } + @Override + public boolean placeBlockAt(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ) + { + int angle = MathHelper.floor_double((player.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3; + player.sendChatToPlayer("M:"+stack.getItemDamage()+"A:"+angle); + if (!world.setBlockAndMetadataWithNotify(x, y, z, this.blockID, stack.getItemDamage()+angle)) + { + return false; + } + + if (world.getBlockId(x, y, z) == this.blockID) + { + Block.blocksList[this.blockID].updateBlockMetadata(world, x, y, z, side, hitX, hitY, hitZ); + Block.blocksList[this.blockID].onBlockPlacedBy(world, x, y, z, player); + } + + return true; + } + +} diff --git a/src/common/assemblyline/interaction/TileEntityEjector.java b/src/common/assemblyline/interaction/TileEntityEjector.java new file mode 100644 index 00000000..c41563a5 --- /dev/null +++ b/src/common/assemblyline/interaction/TileEntityEjector.java @@ -0,0 +1,334 @@ +package assemblyline.interaction; + +import java.util.List; + +import net.minecraft.src.AxisAlignedBB; +import net.minecraft.src.Entity; +import net.minecraft.src.EntityItem; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.Packet; +import net.minecraft.src.Packet250CustomPayload; +import net.minecraft.src.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.core.Vector3; +import universalelectricity.implement.IElectricityReceiver; +import universalelectricity.prefab.network.IPacketReceiver; +import universalelectricity.prefab.network.PacketManager; +import assemblyline.TileEntityBase; +import assemblyline.belts.TileEntityConveyorBelt; + +import com.google.common.io.ByteArrayDataInput; + +import cpw.mods.fml.common.network.PacketDispatcher; + +public class TileEntityEjector extends TileEntityBase implements IElectricityReceiver, IPacketReceiver +{ + /** + * Joules required per tick. + */ + public static final int WATTS_REQUIRED = 10; + + public double wattsReceived = 0; + + public boolean firePiston = false; + public boolean pFirePiston = false; + public boolean rejectItems = true; + public boolean[] onOff = new boolean[] + { true, true, true, true }; + public TileEntityConveyorBelt beltSide = null; + + @Override + public double wattRequest() + { + return WATTS_REQUIRED; + } + + // TODO add computer craft support to change + // onOff values, or even select what can be + // rejected. + // If option two add a rejector item to tell + // the computer what item is in front of the + // ejector + @Override + public void updateEntity() + { + super.updateEntity(); + + if (this.ticks % 10 == 0) + { + int meta = worldObj.getBlockMetadata(xCoord, yCoord, zCoord); + ForgeDirection searchPosition = Vector3.getOrientationFromSide(ForgeDirection.getOrientation(getDirection(meta)), ForgeDirection.SOUTH); + TileEntity tileEntity = worldObj.getBlockTileEntity(xCoord + searchPosition.offsetX, yCoord + searchPosition.offsetY, zCoord + searchPosition.offsetZ); + if (tileEntity instanceof TileEntityConveyorBelt) + { + this.beltSide = (TileEntityConveyorBelt) tileEntity; + } + else + { + this.beltSide = null; + } + this.firePiston = false; + try + { + AxisAlignedBB bounds = AxisAlignedBB.getBoundingBox(xCoord + searchPosition.offsetX, yCoord + searchPosition.offsetY, zCoord + searchPosition.offsetZ, xCoord + searchPosition.offsetX + 1, yCoord + searchPosition.offsetY + 1, zCoord + searchPosition.offsetZ + 1); + List itemsBehind = worldObj.getEntitiesWithinAABB(EntityItem.class, bounds); + + if (itemsBehind.size() > 0 && this.wattsReceived > this.WATTS_REQUIRED) + { + for (EntityItem entity : itemsBehind) + { + if (this.canItemBeThrow(entity)) + { + this.throwItem(searchPosition, entity); + } + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } + + /** + * Used to do the actual throwing of the item + * from the piston arm + * + * @param side + * - used to do the offset + * @param entity + * - Entity being thrown + */ + public void throwItem(ForgeDirection side, Entity entity) + { + this.firePiston = true; + if (this.beltSide != null) + { + this.beltSide.ignore(entity); + + } + entity.motionX = (double) side.offsetX * 0.1; + entity.motionY += 0.10000000298023224D; + entity.motionZ = (double) side.offsetZ * 0.1; + this.wattsReceived -= this.WATTS_REQUIRED; + } + + public boolean canItemBeThrow(Entity entity) + { + // TODO add ability to eject Entities that + // are not items, though i might want to + // create a bigger ejector for this + // TODO might also want to add damaging + // effect to items like glass once i make + // a sorter arm + if (entity instanceof EntityItem) + { + EntityItem itemE = (EntityItem) entity; + ItemStack item = itemE.item; + + if (this.rejectItems) + { + + // reject the items with same IDS + // as those placed in inventory + for (int i = 0; i < this.containingItems.length; i++) + { + if (containingItems[i] != null) + { + if (containingItems[i].itemID == item.itemID && containingItems[i].getItemDamage() == item.getItemDamage()) { return true; } + } + } + return false; + + } + else if (!this.rejectItems) + { + // reject all but the items with + // same IDS as those placed in + // inventory + for (int i = 0; i < this.containingItems.length; i++) + { + if (containingItems[i] != null) + { + if (containingItems[i].itemID == item.itemID && containingItems[i].getItemDamage() == item.getItemDamage()) { return false; } + } + } + return true; + } + } + return false; + } + + public byte getDirection(int meta) + { + + switch (meta) + { + case 0: + return 2; + case 1: + return 5; + case 2: + return 3; + case 3: + return 4; + } + return 0; + } + + @Override + public boolean canReceiveFromSide(ForgeDirection side) + { + // TODO Auto-generated method stub + return side == ForgeDirection.DOWN; + } + + /* + * @Override public Object[] sendDataA() { + * return new Object[] { this.firePiston, + * this.rejectItems }; } + * + * @Override public Object[] sendDataG() { + * Object[] data = new + * Object[this.onOff.length]; for (int i = 0; + * i < this.onOff.length; i++) { data[i] = + * onOff[i]; } return data; } + * + * @Override public void + * guiPacket(NetworkManager network, int + * packetType, Packet250CustomPayload packet, + * EntityPlayer player, ByteArrayDataInput + * dataStream) { if (worldObj.isRemote) { try + * { for (int i = 0; i < this.onOff.length; + * i++) { this.onOff[i] = + * dataStream.readBoolean(); } + * + * } catch (Exception e) { + * e.printStackTrace(); } } + * + * } + * + * @Override public void + * animationPacket(NetworkManager network, int + * packetType, Packet250CustomPayload packet, + * EntityPlayer player, ByteArrayDataInput + * dataStream) { if (worldObj.isRemote) { try + * { this.firePiston = + * dataStream.readBoolean(); this.rejectItems + * = dataStream.readBoolean(); + * + * } catch (Exception e) { + * e.printStackTrace(); } } + * + * } + * + * @Override public void + * otherPacket(NetworkManager network, int + * packetType, Packet250CustomPayload packet, + * EntityPlayer player, ByteArrayDataInput + * dataStream) { if (worldObj.isRemote) { try + * { + * + * } catch (Exception e) { + * e.printStackTrace(); } } else if + * (!worldObj.isRemote) { try { int ID = + * dataStream.readInt(); if (ID == 0) { + * this.changeOnOff(dataStream.readInt()); } + * else if (ID == 1) { this.changeRejected(); + * } + * + * } catch (Exception e) { + * e.printStackTrace(); } } + * + * } + */ + + public void changeOnOff(int i) + { + if (i >= this.onOff.length) { return; } + boolean cc = this.onOff[i]; + if (cc) + { + cc = false; + } + else + { + cc = true; + } + this.onOff[i] = cc; + if (worldObj.isRemote) + { + Packet packet = PacketManager.getPacket("asmLine", this, new Object[] + { 2, 0, i }); + PacketDispatcher.sendPacketToServer(packet); + } + } + + public void changeRejected() + { + + boolean cc = this.rejectItems; + if (cc) + { + cc = false; + } + else + { + cc = true; + } + this.rejectItems = cc; + if (worldObj.isRemote) + { + Packet packet = PacketManager.getPacket("asmLine", this, new Object[] + { 2, 1 }); + PacketDispatcher.sendPacketToServer(packet); + } + } + + @Override + public void readFromNBT(NBTTagCompound nbt) + { + super.readFromNBT(nbt); + for (int i = 0; i < this.onOff.length; i++) + { + this.onOff[i] = nbt.getBoolean("onOff" + i); + } + this.rejectItems = nbt.getBoolean("reject"); + } + + /** + * Writes a tile entity to NBT. + */ + @Override + public void writeToNBT(NBTTagCompound nbt) + { + super.writeToNBT(nbt); + for (int i = 0; i < this.onOff.length; i++) + { + nbt.setBoolean("onOff" + i, this.onOff[i]); + } + nbt.setBoolean("reject", this.rejectItems); + } + + @Override + public String getInvName() + { + return "Ejector"; + } + + @Override + public int getInventoryStackLimit() + { + return 1; + } + + @Override + public void onReceive(TileEntity sender, double amps, double voltage, ForgeDirection side) + { + this.wattsReceived += (amps * voltage); + + } +} diff --git a/src/common/assemblyline/interaction/TileEntityMachineInput.java b/src/common/assemblyline/interaction/TileEntityMachineInput.java new file mode 100644 index 00000000..d2431a4d --- /dev/null +++ b/src/common/assemblyline/interaction/TileEntityMachineInput.java @@ -0,0 +1,307 @@ +package assemblyline.interaction; + +import java.util.List; + +import net.minecraft.src.AxisAlignedBB; +import net.minecraft.src.EntityItem; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.IInventory; +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.NBTTagList; +import net.minecraft.src.Packet250CustomPayload; +import net.minecraft.src.TileEntity; +import net.minecraft.src.TileEntityChest; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.prefab.TileEntityElectricityReceiver; +import universalelectricity.prefab.network.IPacketReceiver; + +import com.google.common.io.ByteArrayDataInput; + +public class TileEntityMachineInput extends TileEntityElectricityReceiver implements IPacketReceiver,IInventory { + public float energyReq = .1f; + public float energyMax = 10f; + public float energyStor = 0f; + private ItemStack[] containingItems = new ItemStack[1]; + public ForgeDirection dir = ForgeDirection.DOWN; + private int count = 0; + @Override + public double wattRequest() { + return energyMax-energyStor; + } + @Override + public void updateEntity() + { + if(count++ >=10){ + count = 0; + if(!isDisabled()) + { + int meta = worldObj.getBlockMetadata(xCoord, yCoord, zCoord); + ForgeDirection searchPosition = ForgeDirection.getOrientation(this.getBeltDirection()); + dir = searchPosition; + try + { + AxisAlignedBB bounds = AxisAlignedBB.getBoundingBox(xCoord+searchPosition.offsetX,yCoord+ searchPosition.offsetY,zCoord+ searchPosition.offsetZ, xCoord+searchPosition.offsetX+1,yCoord+ searchPosition.offsetY+1,zCoord+ searchPosition.offsetZ+1); + TileEntity bEnt = worldObj.getBlockTileEntity(xCoord+searchPosition.getOpposite().offsetX,yCoord+ searchPosition.getOpposite().offsetY,zCoord+ searchPosition.getOpposite().offsetZ); + List itemsBehind = worldObj.getEntitiesWithinAABB(EntityItem.class, bounds); + ItemStack tItem = this.containingItems[0]; + if(itemsBehind.size() > 0 && this.energyStor > this.energyReq && bEnt instanceof IInventory) + { energyStor -= energyReq; + + for(EntityItem entity : itemsBehind) + { + ItemStack eStack = entity.item; + int ite = eStack.stackSize; + if(bEnt instanceof TileEntityChest) + { + TileEntityChest bEntChest2 = null; + TileEntityChest bEntChest = (TileEntityChest)bEnt; + for(int i = 2; i<6; i++) + { + ForgeDirection si = ForgeDirection.getOrientation(i); + if(worldObj.getBlockTileEntity(xCoord+dir.getOpposite().offsetX+si.offsetX, yCoord+dir.getOpposite().offsetY+si.offsetY, zCoord+dir.getOpposite().offsetZ+si.offsetZ) instanceof TileEntityChest) + { + bEntChest2 = (TileEntityChest) worldObj.getBlockTileEntity(xCoord+dir.getOpposite().offsetX+si.offsetX, yCoord+dir.getOpposite().offsetY+si.offsetY, zCoord+dir.getOpposite().offsetZ+si.offsetZ); + break; + } + } + if(eStack != null && eStack.stackSize > 0){ + for(int i =0; i < bEntChest.getSizeInventory(); i++) + { + + ItemStack stack = bEntChest.getStackInSlot(i); + if(stack == null) + { + bEntChest.setInventorySlotContents(i, eStack); + entity.setDead(); + eStack = null; + break; + }else + if(stack.getItem().equals(eStack.getItem()) && stack.getItemDamage() == eStack.getItemDamage()) + { + int rej = Math.max((stack.stackSize + eStack.stackSize) - stack.getItem().getItemStackLimit(), 0); + stack.stackSize = Math.min(Math.max((stack.stackSize + eStack.stackSize - rej),0),stack.getItem().getItemStackLimit()); + eStack.stackSize = rej; + bEntChest.setInventorySlotContents(i, stack); + if(eStack.stackSize <= 0) + { + entity.setDead(); + eStack = null; + break; + } + + } + + } + } + if(bEntChest2 != null && eStack != null && eStack.stackSize > 0) + { + for(int i =0; i < bEntChest2.getSizeInventory(); i++) + { + ItemStack stack = bEntChest2.getStackInSlot(i); + if(stack == null) + { + bEntChest2.setInventorySlotContents(i, eStack); + entity.setDead(); + eStack = null; + break; + }else + if(stack.getItem().equals(eStack.getItem()) && stack.getItemDamage() == eStack.getItemDamage()) + { + int rej = Math.max((stack.stackSize + eStack.stackSize) - stack.getItem().getItemStackLimit(), 0); + stack.stackSize = Math.min(Math.max((stack.stackSize + eStack.stackSize - rej),0),stack.getItem().getItemStackLimit()); + eStack.stackSize = rej; + bEntChest2.setInventorySlotContents(i, stack); + if(eStack.stackSize <= 0) + { + entity.setDead(); + eStack = null; + break; + } + } + } + }if(entity != null && eStack != null){ + if(eStack != null && eStack.stackSize <= 0) + { + entity.setDead(); + eStack = null; + break; + }else + { + entity.setDead(); + EntityItem var23 = new EntityItem(worldObj, entity.posX, entity.posY + 0.1D, entity.posZ, eStack); + worldObj.spawnEntityInWorld(var23); + }} + + }//end chest trade + //TODO setup for ISideInventory + } + } + }catch(Exception e) + { + e.printStackTrace(); + } + + } + } + } + public int getBeltDirection() + { + int meta = worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord); + if(meta >= 4 && meta < 8) + { + switch(meta) + { + case 4: return 2; + case 5: return 5; + case 6: return 3; + case 7: return 4; + } + } + return 0; + } + @Override + public boolean canReceiveFromSide(ForgeDirection side) { + if(side == dir ||side == dir.getOpposite()) + { + return false; + } + return true; + } + @Override + public void readFromNBT(NBTTagCompound par1NBTTagCompound) + { + super.readFromNBT(par1NBTTagCompound); + NBTTagList var2 = par1NBTTagCompound.getTagList("Items"); + this.containingItems = new ItemStack[this.getSizeInventory()]; + + for (int var3 = 0; var3 < var2.tagCount(); ++var3) + { + NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3); + byte var5 = var4.getByte("Slot"); + + if (var5 >= 0 && var5 < this.containingItems.length) + { + this.containingItems[var5] = ItemStack.loadItemStackFromNBT(var4); + } + } + } + /** + * Writes a tile entity to NBT. + */ + @Override + public void writeToNBT(NBTTagCompound par1NBTTagCompound) + { + super.writeToNBT(par1NBTTagCompound); + NBTTagList var2 = new NBTTagList(); + + for (int var3 = 0; var3 < this.containingItems.length; ++var3) + { + if (this.containingItems[var3] != null) + { + NBTTagCompound var4 = new NBTTagCompound(); + var4.setByte("Slot", (byte)var3); + this.containingItems[var3].writeToNBT(var4); + var2.appendTag(var4); + } + } + + par1NBTTagCompound.setTag("Items", var2); + } + @Override + public int getSizeInventory() + { + return this.containingItems.length; + } + @Override + public ItemStack getStackInSlot(int par1) + { + return this.containingItems[par1]; + } + @Override + public ItemStack decrStackSize(int par1, int par2) + { + if (this.containingItems[par1] != null) + { + ItemStack var3; + + if (this.containingItems[par1].stackSize <= par2) + { + var3 = this.containingItems[par1]; + this.containingItems[par1] = null; + return var3; + } + else + { + var3 = this.containingItems[par1].splitStack(par2); + + if (this.containingItems[par1].stackSize == 0) + { + this.containingItems[par1] = null; + } + + return var3; + } + } + else + { + return null; + } + } + @Override + public ItemStack getStackInSlotOnClosing(int par1) + { + if (this.containingItems[par1] != null) + { + ItemStack var2 = this.containingItems[par1]; + this.containingItems[par1] = null; + return var2; + } + else + { + return null; + } + } + @Override + public void setInventorySlotContents(int par1, ItemStack par2ItemStack) + { + this.containingItems[par1] = par2ItemStack; + + if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) + { + par2ItemStack.stackSize = this.getInventoryStackLimit(); + } + } + @Override + public String getInvName() + { + return "Ejector"; + } + @Override + public int getInventoryStackLimit() + { + //TODO change + return 0; + } + @Override + public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) + { + return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : par1EntityPlayer.getDistanceSq(this.xCoord + 0.5D, this.yCoord + 0.5D, this.zCoord + 0.5D) <= 64.0D; + } + @Override + public void openChest() { } + @Override + public void closeChest() { } + @Override + public void onReceive(TileEntity sender, double amps, double voltage, + ForgeDirection side) { + this.energyStor+=(amps*voltage); + + } + @Override + public void handlePacketData(NetworkManager network, int packetType, + Packet250CustomPayload packet, EntityPlayer player, + ByteArrayDataInput dataStream) { + + } +} diff --git a/src/common/assemblyline/mcmod.info b/src/common/assemblyline/mcmod.info new file mode 100644 index 00000000..645c6ce1 --- /dev/null +++ b/src/common/assemblyline/mcmod.info @@ -0,0 +1,21 @@ +[ +{ + "modid": "asmLine", + "name": "Assemble Line", + "description": "This mod is a revamp of Calclavia's and ElusiveHawk's Conveyor belts in the form of a factory assemble line", + "version": "0.0.4", + "mcversion": "1.3.2", + "url": "http://www.minecraftforge.net/forum/index.php/board,50.0.html", + "updateUrl": "", + "authors": [ + "DarkGuardsman" + ], + "credits": "Orignal Devs Calclavia,ElusiveHawk", + "logoFile": "", + "screenshots": [ + ], + "parent":"", + "dependencies": ["UE" + ] +} +] \ No newline at end of file diff --git a/src/common/buildcraft/api/tools/IToolWrench.java b/src/common/buildcraft/api/tools/IToolWrench.java new file mode 100644 index 00000000..f9a90f87 --- /dev/null +++ b/src/common/buildcraft/api/tools/IToolWrench.java @@ -0,0 +1,35 @@ +package buildcraft.api.tools; + +import net.minecraft.src.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 + */ + public 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 + */ + public void wrenchUsed(EntityPlayer player, int x, int y, int z); +} diff --git a/src/common/dan200/computer/api/IComputerAccess.java b/src/common/dan200/computer/api/IComputerAccess.java new file mode 100644 index 00000000..52a034e2 --- /dev/null +++ b/src/common/dan200/computer/api/IComputerAccess.java @@ -0,0 +1,131 @@ + +package dan200.computer.api; + +/** + * The interface passed to peripherals by computers or turtles, providing methods + * that they can call. This should not be implemented by your classes. Do not interact + * with computers except via this interface. + */ +public interface IComputerAccess +{ + /** + * Creates a new numbered directory in a subPath of the users game save, and return that number. To be used with mountSaveDir.
+ * For example: n = createNewSaveDir( "computer/cdrom" ), will create a new + * numbered folder in the "computer/cdrom" subdirectory of the users save file, and return that number. + * mountSaveDir( "computer/rom", n ) could then be used to mount that folder onto the computers directory + * structure, and the value n could be saved out and used again in future to give the peripheral + * persistant storage. + * @param subPath A relative file path from the users world save, where the directory should be located. + * @return The numeric represenation of the name of the folder created. Will be positive. + * @see #mountSaveDir(String, String, int, boolean, long) + */ + public int createNewSaveDir( String subPath ); + + /** + * Equivalent to mountSaveDir( String desiredLocation, String subPath, int id, boolean readOnly, long spaceLimit ) with no space limit. + * Mounts created with this method will have unlimited capacity. + * @see #mountSaveDir(String, String, int, boolean, long) + */ + public String mountSaveDir( String desiredLocation, String subPath, int id, boolean readOnly ); + + /** + * Mounts a directory into the computers file system, from a real directory a subPath of the users game save, + * with a numerical name. To be used with createNewSaveDir.
+ * For example: n = createNewSaveDir( "computer/cdrom" ), will create a new + * numbered folder in the "computer/cdrom" subdirectory of the users save file, and return that number. + * mountSaveDir( "computer/rom", n ) could then be used to mount that folder onto the computers directory + * structure, and the value n can be saved out by the peripheral and used again, to give the peripheral + * persistant storage.
+ * When a directory is mounted, it will appear in the computers file system, and the user will be + * able to use file operation to read from and write to the directory (unless readOnly, then only writes will be allowed). + * @param desiredLocation The desired location in the computers file system where you would like the directory to appear. + * If this location already exists, a number will be appended until a free name is found, and the + * actual location will be returned. eg: "cdrom" can become "cdrom2" if two peripherals attempt to + * mount "cdrom", or a "cdrom" folder already exists. + * @param subPath The real relative file path from the users world save, where the directory to mount can be located. + * @param id The numerical name of the folder to mount from the subPath: ex: mountSaveDir( "cdrom", "computer/cdrom", 7 ) + * will mount the directory "computer/cdrom/7". Use createNewSaveDir to obtain a unique directory id. + * @param readOnly Whether the computer will be disallowed from making changes to the mounted directory and modifing or creating files therin. + * @param spaceLimit The size limit of the mount, in bytes. + * @return The location in the computers file system where the directory was mounted. This may differ from "desiredLocation", so the + * return value should be kept track of so the folder can be unmounted later. + * @see #createNewSaveDir(String) + * @see #mountFixedDir(String, String, boolean, long) + * @see #unmount(String) + */ + public String mountSaveDir( String desiredLocation, String subPath, int id, boolean readOnly, long spaceLimit ); + + /** + * Equivalent to mountFixedDir( String desiredLocation, String path, boolean readOnly, long spaceLimit ) with no space limit. + * Mounts created with this method will have unlimited capacity. + * @see #mountFixedDir(String, String, boolean, long) + */ + public String mountFixedDir( String desiredLocation, String path, boolean readOnly ); + + /** + * Mounts a directory into the computers file system, from a real directory in the Minecraft install folder.
+ * For example: mountFixedDir( "stuff", "mods/mymod/lua/stuff", true ), will mount the "lua/stuff" folder from + * your mod's directory into the computers filesystem at the location "stuff", with readonly permission, giving the + * computer access to those files.
+ * When a directory is mounted, it will appear in the computers file system, and the user will be + * able to use file operation to read from and write to the directory (unless readOnly, then only writes will be allowed).
+ * mountFixedDir can also be used to mount files, for example: mountFixedDir( "rom/apis/myapi", "mods/mymod/lua/myapi.lua", true ) can + * be used to have the peripheral install an API onto the computer it attaches to. + * @param desiredLocation The desired location in the computers file system where you would like the directory to appear. + * If this location already exists, a number will be appended until a free name is found, and the + * actual location will be returned. eg: "cdrom" can become "cdrom2" if two peripherals attempt to + * mount "cdrom", or a "cdrom" folder already exists. + * @param subPath The real relative file path from the minecraft install root, where the directory to mount can be located. + * @param readOnly Whether the computer will be disallowed from making changes to the mounted directory and modifing or creating files therin. + * @param spaceLimit The size limit of the mount, in bytes. + * @return The location in the computers file system where the directory was mounted. This may differ from "desiredLocation", so the + * return value should be kept track of so the folder can be unmounted later. + * @see #mountSaveDir(String, String, int, boolean, long) + * @see #unmount(String) + */ + public String mountFixedDir( String desiredLocation, String path, boolean readOnly, long spaceLimit ); + + /** + * Unmounts a directory previously mounted onto the computers file system by mountSaveDir or mountFixedDir.
+ * When a directory is unmounted, it will disappear from the computers file system, and the user will no longer be able to + * access it. All directories mounted by a mountFixedDir or mountSaveDir are automatically unmounted when the peripheral + * is attached if they have not been explicitly unmounted. + * @param location The desired location in the computers file system of the directory to unmount. + * This must be the location of a directory previously mounted by mountFixedDir() or mountSaveDir(), as + * indicated by their return value. + * @see #mountSaveDir(String, String, int, boolean, long) + * @see #mountFixedDir(String, String, boolean, long) + */ + public void unmount( String location ); + + /** + * Returns the numerical ID of this computer.
+ * This is the same number obtained by calling os.getComputerID() or running the "id" program from lua, + * and is guarunteed unique. This number will be positive. + * @return The identifier. + */ + public int getID(); + + /** + * Equivalent to queueEvent( String event, Object[] arguments ) with an empty arguments array. + * @see #queueEvent(String, Object[]) + */ + public void queueEvent( String event ); + + /** + * Causes an event to be raised on this computer, which the computer can respond to by calling + * os.pullEvent(). This can be used to notify the computer when things happen in the world or to + * this peripheral. + * @param event A string identifying the type of event that has occurred, this will be + * returned as the first value from os.pullEvent(). It is recommended that you + * you choose a name that is unique, and recognisable as originating from your + * peripheral. eg: If your peripheral type is "button", a suitable event would be + * "button_pressed". + * @param arguments In addition to a name, you may pass an array of extra arguments to the event, that will + * be supplied as extra return values to os.pullEvent(). Objects in the array will be converted + * to lua data types in the same fashion as the return values of IPeripheral.callMethod().
+ * You may supply null to indicate that no arguments are to be supplied. + * @see IPeripheral#callMethod + */ + public void queueEvent( String event, Object[] arguments ); +} diff --git a/src/common/dan200/computer/api/IPeripheral.java b/src/common/dan200/computer/api/IPeripheral.java new file mode 100644 index 00000000..8dfeb8dc --- /dev/null +++ b/src/common/dan200/computer/api/IPeripheral.java @@ -0,0 +1,103 @@ + +package dan200.computer.api; + +/** + * The interface that defines a peripheral. This should be implemented by the + * TileEntity of any block that you wish to be interacted with by + * computer or turtle. + */ +public interface IPeripheral +{ + /** + * Should return a string that uniquely identifies this type of peripheral. + * This can be queried from lua by calling peripheral.getType() + * @return A string identifying the type of peripheral. + */ + public String getType(); + + /** + * Should return an array of strings that identify the methods that this + * peripheral exposes to Lua. This will be called once before each attachment, + * and should not change when called multiple times. + * @return An array of strings representing method names. + * @see #callMethod + */ + public String[] getMethodNames(); + + /** + * This is called when a lua program on an attached computer calls peripheral.call() with + * one of the methods exposed by getMethodNames().
+ *
+ * Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe + * when interacting with minecraft objects. + * @param computer The interface to the computer that is making the call. Remember that multiple + * computers can be attached to a peripheral at once. + * @param method An integer identifying which of the methods from getMethodNames() the computer + * wishes to call. The integer indicates the index into the getMethodNames() table + * that corresponds to the string passed into peripheral.call() + * @param arguments An array of objects, representing the arguments passed into peripheral.call().
+ * Lua values of type "string" will be represented by Object type String.
+ * Lua values of type "number" will be represented by Object type Double.
+ * Lua values of type "boolean" will be represented by Object type Boolean.
+ * Lua values of any other type will be represented by a null object.
+ * This array will be empty if no arguments are passed. + * @return An array of objects, representing values you wish to return to the lua program.
+ * Integers, Doubles, Floats, Strings, Booleans and null be converted to their corresponding lua type.
+ * All other types will be converted to nil.
+ * You may return null to indicate no values should be returned. + * @throws Exception If you throw any exception from this function, a lua error will be raised with the + * same message as your exception. Use this to throw appropriate errors if the wrong + * arguments are supplied to your method. + * @see #getMethodNames + */ + public Object[] callMethod( IComputerAccess computer, int method, Object[] arguments ) throws Exception; + + /** + * Is called before the computer attempts to attach to the peripheral, and should return whether to allow + * the attachment. Use this to restrict the number of computers that can attach, or to limit attachments to + * certain world directions.
+ * If true is returned, attach() will be called shortly afterwards, and the computer will be able to make method calls. + * If false is returned, attach() will not be called, and the peripheral will be invisible to the computer. + * @param side The world direction (0=bottom, 1=top, etc) that the computer lies relative to the peripheral. + * @return Whether to allow the attachment, as a boolean. + * @see #attach + */ + public boolean canAttachToSide( int side ); + + /** + * Is called when canAttachToSide has returned true, and a computer is attaching to the peripheral. + * This will occur when a peripheral is placed next to an active computer, when a computer is turned on next to a peripheral, + * or when a turtle travels into a square next to a peripheral. + * Between calls to attach() and detach(), the attached computer can make method calls on the peripheral using peripheral.call(). + * This method can be used to keep track of which computers are attached to the peripheral, or to take action when attachment + * occurs.
+ *
+ * Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe + * when interacting with minecraft objects. + * @param computer The interface to the computer that is being attached. Remember that multiple + * computers can be attached to a peripheral at once. + * @param computerSide A string indicating which "side" of the computer the peripheral is attaching, + * relative to the computers orientation. This value will be one of "top", "bottom", + * "left", "right", "front" or "back". This can be used to uniquely identify the + * peripheral when raising events or returning values to the computer. + * @see #canAttachToSide + * @see #detach + */ + public void attach( IComputerAccess computer, String computerSide ); + + /** + * Is called when a computer is detaching from the peripheral. + * This will occur when a computer shuts down, when the peripheral is removed while attached to computers, + * or when a turtle moves away from a square attached to a peripheral. + * This method can be used to keep track of which computers are attached to the peripheral, or to take action when detachment + * occurs.
+ *
+ * Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe + * when interacting with minecraft objects. + * @param computer The interface to the computer that is being detached. Remember that multiple + * computers can be attached to a peripheral at once. + * @see #canAttachToSide + * @see #detach + */ + public void detach( IComputerAccess computer ); +} diff --git a/src/common/universalelectricity/core/UEConfig.java b/src/common/universalelectricity/core/UEConfig.java new file mode 100644 index 00000000..244085a9 --- /dev/null +++ b/src/common/universalelectricity/core/UEConfig.java @@ -0,0 +1,50 @@ +package universalelectricity.core; + +import net.minecraftforge.common.Configuration; + +public class UEConfig +{ + public static int getConfigData(Configuration configuration, String name, int defaultInt) + { + configuration.load(); + int returnInt = defaultInt; + returnInt = Integer.parseInt(configuration.get(name, Configuration.CATEGORY_GENERAL, defaultInt).value); + configuration.save(); + return returnInt; + } + + public static boolean getConfigData(Configuration configuration, String name, boolean defaultBoolean) + { + configuration.load(); + boolean returnBoolean = defaultBoolean; + returnBoolean = Boolean.parseBoolean(configuration.get(name, Configuration.CATEGORY_GENERAL, defaultBoolean).value); + configuration.save(); + return returnBoolean; + } + + public static int getBlockConfigID(Configuration configuration, String name, int defaultID) + { + configuration.load(); + int id = defaultID; + + id = Integer.parseInt(configuration.getBlock(name, defaultID).value); + + if (id <= 136) { return defaultID; } + + configuration.save(); + return id; + } + + public static int getItemConfigID(Configuration configuration, String name, int defaultID) + { + configuration.load(); + int id = defaultID; + + id = Integer.parseInt(configuration.getItem(name, Configuration.CATEGORY_ITEM, defaultID).value); + + if (id < 256) { return defaultID; } + + configuration.save(); + return id; + } +} diff --git a/src/common/universalelectricity/core/UELoader.java b/src/common/universalelectricity/core/UELoader.java new file mode 100644 index 00000000..c55205c0 --- /dev/null +++ b/src/common/universalelectricity/core/UELoader.java @@ -0,0 +1,68 @@ +package universalelectricity.core; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.ForgeSubscribe; +import net.minecraftforge.event.world.WorldEvent.Load; +import net.minecraftforge.event.world.WorldEvent.Unload; +import universalelectricity.electricity.ElectricityManager; +import universalelectricity.electricity.ElectricityManagerTicker; +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.Side; +import cpw.mods.fml.common.registry.TickRegistry; + +/** + * A class used to load Universal Electricity and make it work. + * @author Calclavia + * + */ +public class UELoader +{ + public static final UELoader INSTANCE = new UELoader(); + + public static boolean isInitialized = false; + + public void initiate() + { + if (!isInitialized) + { + TickRegistry.registerTickHandler(new ElectricityManagerTicker(), Side.SERVER); + ElectricityManager.instance = new ElectricityManager(); + MinecraftForge.EVENT_BUS.register(this); + + if (UniversalElectricity.BC3_RATIO <= 0 || !Loader.isModLoaded("BuildCraft|Core")) + { + FMLLog.fine("Disabled Buildcraft electricity conversion!"); + } + else + { + FMLLog.fine("Buildcraft conversion ratio: " + UniversalElectricity.BC3_RATIO); + } + + if (UniversalElectricity.IC2_RATIO <= 0 || !Loader.isModLoaded("IC2")) + { + FMLLog.fine("Disabled Industrialcraft electricity conversion!"); + } + else + { + FMLLog.fine("IC2 conversion ratio: " + UniversalElectricity.IC2_RATIO); + } + + FMLLog.finest("Universal Electricity v" + UniversalElectricity.VERSION + " successfully loaded!"); + + isInitialized = true; + } + } + + @ForgeSubscribe + public void onWorldLoad(Load event) + { + ElectricityManagerTicker.inGameTicks = 0; + } + + @ForgeSubscribe + public void onWorldUnload(Unload event) + { + ElectricityManager.instance = new ElectricityManager(); + } +} diff --git a/src/common/universalelectricity/core/UniversalElectricity.java b/src/common/universalelectricity/core/UniversalElectricity.java new file mode 100644 index 00000000..3db01584 --- /dev/null +++ b/src/common/universalelectricity/core/UniversalElectricity.java @@ -0,0 +1,119 @@ +package universalelectricity.core; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.src.MapColor; +import net.minecraft.src.Material; +import net.minecraftforge.common.Configuration; +import net.minecraftforge.common.ForgeVersion; +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.Loader; + +/** + * Instructions for using the Universal Electricity API. + * + * The less you include of the API, the more compatible your + * mod will be for future releases of Universal Electricity. + * + * REQUIRED PACKAGES: + * "universalelectricity" + * "universalelectricity.electricity" + * "universalelectricity.implements" - Some interfaces can be removed if not needed. + * + * The rest of the classes should be removed if you are not going to use them. + * + * @author Calclavia + * + */ +public class UniversalElectricity +{ + /** + * The version of the Universal Electricity API. + */ + public static final int MAJOR_VERSION = 1; + public static final int MINOR_VERSION = 0; + public static final int REVISION_VERSION = 0; + public static final String VERSION = MAJOR_VERSION + "." + MINOR_VERSION + "." + REVISION_VERSION; + + /** + * The Universal Electricity configuration file. + */ + public static final Configuration CONFIGURATION = new Configuration(new File(Loader.instance().getConfigDir(), "UniversalElectricity/UniversalElectricity.cfg")); + + /** + * Conversion ratios between Buildcraft and Industrialcraft energy. + */ + // EU to Watts ratio + public static final float IC2_RATIO = (float) UEConfig.getConfigData(CONFIGURATION, "IndustrialCraft Conversion Ratio", 7); + // MJ to Watts ratio. + public static final float BC3_RATIO = (float) UEConfig.getConfigData(CONFIGURATION, "BuildCraft Conversion Ratio", 85);; + public static final float TO_IC2_RATIO = 1 / IC2_RATIO; + public static final float TO_BC_RATIO = 1 / BC3_RATIO; + + /** + * Use this material for all your machine blocks. It can be breakable by + * hand. + */ + public static final Material machine = new Material(MapColor.ironColor); + + public static final List mods = new ArrayList(); + + /** + * You must register your mod with Universal Electricity. Call this in your + * mod's pre-initialization stage. + */ + public static void register(Object mod, int major, int minor, int revision, boolean strict) + { + if (MAJOR_VERSION != major) { throw new RuntimeException("Universal Electricity wrong version! Require v" + major + "." + minor + "." + revision); } + + if (MINOR_VERSION < minor) { throw new RuntimeException("Universal Electricity minor version is too old! Require v" + major + "." + minor + "." + revision); } + + if (REVISION_VERSION < revision) + { + if (strict) + { + throw new RuntimeException("Universal Electricity is too old! Require v" + major + "." + minor + "." + revision); + } + else + { + FMLLog.warning("Universal Electricity is not the specified version. Odd things might happen. Recommend to have v" + major + "." + minor + "." + revision); + } + } + + mods.add(mod); + + FMLLog.fine(mod.getClass().getSimpleName()+" has been registered to Universal Electricity."); + + UELoader.INSTANCE.initiate(); + } + + /** + * A function that allows you to lock your mod to a specific version of + * Forge. + */ + public static void forgeLock(int major, int minor, int revision, boolean strict) + { + if (ForgeVersion.getMajorVersion() != major) { throw new RuntimeException("Universal Electricity: Wrong Minecraft Forge version! Require " + major + "." + minor + "." + revision); } + + if (ForgeVersion.getMinorVersion() < minor) { throw new RuntimeException("Universal Electricity: Minecraft Forge minor version is too old! Require " + major + "." + minor + "." + revision); } + + if (ForgeVersion.getRevisionVersion() < revision) + { + if (strict) + { + throw new RuntimeException("Universal Electricity: Minecraft Forge revision version is too old! Require " + major + "." + minor + "." + revision); + } + else + { + System.out.println("Universal Electricity Warning: Minecraft Forge is not the specified version. Odd things might happen. Require " + major + "." + minor + "." + revision); + } + } + } + + public static void forgeLock(int major, int minor, int revision) + { + forgeLock(major, minor, revision, false); + } +} diff --git a/src/common/universalelectricity/core/Vector2.java b/src/common/universalelectricity/core/Vector2.java new file mode 100644 index 00000000..b7f3373e --- /dev/null +++ b/src/common/universalelectricity/core/Vector2.java @@ -0,0 +1,106 @@ +package universalelectricity.core; + +import net.minecraft.src.MathHelper; + +/** + * Vector2 Class is used for defining objects in a 2D space. Vector2 makes it + * easier to handle the coordinates of objects. Instead of fumbling with x and y + * variables, all x and y variables are stored in one class. Vector3.x, + * Vector3.y. + * + * @author Calclavia + */ + +public class Vector2 implements Cloneable +{ + public double x; + public double y; + + public Vector2() + { + this(0, 0); + } + + public Vector2(int x, int y) + { + this.x = x; + this.y = y; + } + + public Vector2(double x, double y) + { + this.x = x; + this.y = y; + } + + // Returns the values as an int + public int intX() + { + return (int) Math.floor(this.x); + } + + public int intY() + { + return (int) Math.floor(this.y); + } + + /** + * Makes a new copy of this Vector. Prevents variable referencing problems. + */ + @Override + public Vector2 clone() + { + return new Vector2(this.x, this.y); + } + + public static boolean isPointInRegion(Vector2 point, Vector2 minPoint, Vector2 maxPoint) + { + return (point.x > minPoint.x && point.x < maxPoint.x) && (point.y > minPoint.y && point.y < maxPoint.y); + } + + public static double distance(Vector2 par1, Vector2 par2) + { + double var2 = par1.x - par2.x; + double var4 = par1.y - par2.y; + return MathHelper.sqrt_double(var2 * var2 + var4 * var4); + } + + public static double slope(Vector2 par1, Vector2 par2) + { + double var2 = par1.x - par2.x; + double var4 = par1.y - par2.y; + return var4 / var2; + } + + public void add(Vector2 par1) + { + this.x += par1.x; + this.y += par1.y; + } + + public void add(double par1) + { + this.x += par1; + this.y += par1; + } + + public Vector2 round() + { + return new Vector2(Math.round(this.x), Math.round(this.y)); + } + + public Vector2 floor() + { + return new Vector2(Math.floor(this.x), Math.floor(this.y)); + } + + public String output() + { + return "Vector2: " + this.x + "," + this.y; + } + + public void printVector() + { + System.out.println(output()); + } +} \ No newline at end of file diff --git a/src/common/universalelectricity/core/Vector3.java b/src/common/universalelectricity/core/Vector3.java new file mode 100644 index 00000000..ee50f979 --- /dev/null +++ b/src/common/universalelectricity/core/Vector3.java @@ -0,0 +1,448 @@ +package universalelectricity.core; + +import net.minecraft.src.ChunkCoordinates; +import net.minecraft.src.Entity; +import net.minecraft.src.MathHelper; +import net.minecraft.src.MovingObjectPosition; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.TileEntity; +import net.minecraft.src.Vec3; +import net.minecraft.src.World; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.implement.IConnector; + +/** + * Vector3 Class is used for defining objects in a 3D space. Vector3 makes it + * easier to handle the coordinates of objects. Instead of fumbling with x, y + * and z variables, all x, y and z variables are stored in one class. Vector3.x, + * Vector3.y, Vector3.z. + * + * @author Calclavia + */ + +public class Vector3 extends Vector2 implements Cloneable +{ + public double z; + + public Vector3() + { + this(0, 0, 0); + } + + public Vector3(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public Vector3(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + + /** + * Returns the coordinates as integers + */ + public int intX() + { + return (int) Math.floor(this.x); + } + + public int intY() + { + return (int) Math.floor(this.y); + } + + public int intZ() + { + return (int) Math.floor(this.z); + } + + /** + * Makes a new copy of this Vector. Prevents variable referencing problems. + */ + @Override + public Vector3 clone() + { + return new Vector3(this.x, this.y, this.z); + } + + /** + * Converts a TileEntity's position into Vector3 + */ + public static Vector3 get(Entity par1) + { + return new Vector3(par1.posX, par1.posY, par1.posZ); + } + + /** + * Converts an entity's position into Vector3 + */ + public static Vector3 get(TileEntity par1) + { + return new Vector3(par1.xCoord, par1.yCoord, par1.zCoord); + } + + /** + * Converts from Vec3 into a Vector3 + */ + public static Vector3 get(Vec3 par1) + { + return new Vector3(par1.xCoord, par1.yCoord, par1.zCoord); + } + + /** + * Converts a MovingObjectPosition to Vector3 + */ + public static Vector3 get(MovingObjectPosition par1) + { + return new Vector3(par1.blockX, par1.blockY, par1.blockZ); + } + + /** + * Converts a MovingObjectPosition to Vector3 + */ + public static Vector3 get(ChunkCoordinates par1) + { + return new Vector3(par1.posX, par1.posY, par1.posZ); + } + + public int getBlockID(World world) + { + return world.getBlockId(this.intX(), this.intY(), this.intZ()); + } + + public int getBlockMetadata(World world) + { + return world.getBlockMetadata(this.intX(), this.intY(), this.intZ()); + } + + public TileEntity getTileEntity(World world) + { + return world.getBlockTileEntity(this.intX(), this.intY(), this.intZ()); + } + + public void setBlock(World world, int id, int metadata) + { + world.setBlockAndMetadata(this.intX(), this.intY(), this.intZ(), id, metadata); + } + + public void setBlock(World world, int id) + { + world.setBlock(this.intX(), this.intY(), this.intZ(), id); + } + + public void setBlockWithNotify(World world, int id, int metadata) + { + world.setBlockAndMetadataWithNotify(this.intX(), this.intY(), this.intZ(), id, metadata); + } + + public void setBlockWithNotify(World world, int id) + { + world.setBlockWithNotify(this.intX(), this.intY(), this.intZ(), id); + } + + /** + * Converts this Vector3 into a Vector2 by dropping the Y axis. + */ + public Vector2 toVector2() + { + return new Vector2(this.x, this.z); + } + + /** + * Converts this vector three into a Minecraft Vec3 object + */ + public Vec3 toVec3() + { + return Vec3.createVectorHelper(this.x, this.y, this.z); + } + + /** + * Checks if a Vector3 point is located inside a region + */ + public static boolean isPointInRegion(Vector3 point, Vector3 minPoint, Vector3 maxPoint) + { + return (point.x > minPoint.x && point.x < maxPoint.x) && (point.y > minPoint.y && point.y < maxPoint.y) && (point.z > minPoint.z && point.z < maxPoint.z); + } + + /** + * Compares two vectors and see if they are equal. True if so. + */ + public boolean isEqual(Vector3 vector3) + { + return (this.x == vector3.x && this.y == vector3.y && this.z == vector3.z); + } + + /** + * Gets the distance between two vectors + * + * @return The distance + */ + public static double distance(Vector3 par1, Vector3 par2) + { + double var2 = par1.x - par2.x; + double var4 = par1.y - par2.y; + double var6 = par1.z - par2.z; + return MathHelper.sqrt_double(var2 * var2 + var4 * var4 + var6 * var6); + } + + public double distanceTo(Vector3 vector3) + { + double var2 = vector3.x - this.x; + double var4 = vector3.y - this.y; + double var6 = vector3.z - this.z; + return MathHelper.sqrt_double(var2 * var2 + var4 * var4 + var6 * var6); + } + + public static Vector3 subtract(Vector3 par1, Vector3 par2) + { + return new Vector3(par1.x - par2.x, par1.y - par2.y, par1.z - par2.z); + } + + public static Vector3 add(Vector3 par1, Vector3 par2) + { + return new Vector3(par1.x + par2.x, par1.y + par2.y, par1.z + par2.z); + } + + public static Vector3 add(Vector3 par1, double par2) + { + return new Vector3(par1.x + par2, par1.y + par2, par1.z + par2); + } + + public void add(Vector3 par1) + { + this.x += par1.x; + this.y += par1.y; + this.z += par1.z; + } + + @Override + public void add(double par1) + { + this.x += par1; + this.y += par1; + this.z += par1; + } + + public static Vector3 multiply(Vector3 par1, Vector3 par2) + { + return new Vector3(par1.x * par2.x, par1.y * par2.y, par1.z * par2.z); + } + + public static Vector3 multiply(Vector3 par1, double par2) + { + return new Vector3(par1.x * par2, par1.y * par2, par1.z * par2); + } + + public static Vector3 readFromNBT(String prefix, NBTTagCompound par1NBTTagCompound) + { + Vector3 tempVector = new Vector3(); + tempVector.x = par1NBTTagCompound.getDouble(prefix + "X"); + tempVector.y = par1NBTTagCompound.getDouble(prefix + "Y"); + tempVector.z = par1NBTTagCompound.getDouble(prefix + "Z"); + return tempVector; + } + + /** + * Saves this Vector3 to disk + * + * @param prefix + * - The prefix of this save. Use some unique string. + * @param par1NBTTagCompound + * - The NBT compound object to save the data in + */ + public void writeToNBT(String prefix, NBTTagCompound par1NBTTagCompound) + { + par1NBTTagCompound.setDouble(prefix + "X", this.x); + par1NBTTagCompound.setDouble(prefix + "Y", this.y); + par1NBTTagCompound.setDouble(prefix + "Z", this.z); + } + + @Override + public Vector3 round() + { + return new Vector3(Math.round(this.x), Math.round(this.y), Math.round(this.z)); + } + + @Override + public Vector3 floor() + { + return new Vector3(Math.floor(this.x), Math.floor(this.y), Math.floor(this.z)); + } + + @Override + public String output() + { + return "Vector3: " + this.x + "," + this.y + "," + this.z; + } + + /** + * Gets a position relative to another position's side + * + * @param position + * - The position + * @param side + * - The side. 0-5 + * @return The position relative to the original position's side + */ + public void modifyPositionFromSide(ForgeDirection side) + { + switch (side.ordinal()) + { + case 0: + this.y -= 1; + break; + case 1: + this.y += 1; + break; + case 2: + this.z -= 1; + break; + case 3: + this.z += 1; + break; + case 4: + this.x -= 1; + break; + case 5: + this.x += 1; + break; + } + } + + public static TileEntity getTileEntityFromSide(World world, Vector3 position, ForgeDirection side) + { + position.modifyPositionFromSide(side); + return world.getBlockTileEntity(position.intX(), position.intY(), position.intZ()); + } + + /** + * Gets a connector unit based on the given side. + */ + public static TileEntity getConnectorFromSide(World world, Vector3 position, ForgeDirection side) + { + TileEntity tileEntity = getTileEntityFromSide(world, position, side); + + if (tileEntity instanceof IConnector) + { + if (((IConnector) tileEntity).canConnect(getOrientationFromSide(side, ForgeDirection.NORTH))) { return tileEntity; } + } + + return null; + } + + /** + * Finds the side of a block depending on it's facing direction from the + * given side. The side numbers are compatible with the + * function"getBlockTextureFromSideAndMetadata". + * + * Bottom: 0; Top: 1; Back: 2; Front: 3; Left: 4; Right: 5; + * + * @param front + * - The direction in which this block is facing/front. Use a + * number between 0 and 5. Default is 3. + * @param side + * - The side you are trying to find. A number between 0 and 5. + * @return The side relative to the facing direction. + */ + + public static ForgeDirection getOrientationFromSide(ForgeDirection front, ForgeDirection side) + { + switch (front.ordinal()) + { + case 0: + switch (side.ordinal()) + { + case 0: + return ForgeDirection.getOrientation(3); + case 1: + return ForgeDirection.getOrientation(2); + case 2: + return ForgeDirection.getOrientation(1); + case 3: + return ForgeDirection.getOrientation(0); + case 4: + return ForgeDirection.getOrientation(5); + case 5: + return ForgeDirection.getOrientation(4); + } + + case 1: + switch (side.ordinal()) + { + case 0: + return ForgeDirection.getOrientation(4); + case 1: + return ForgeDirection.getOrientation(5); + case 2: + return ForgeDirection.getOrientation(0); + case 3: + return ForgeDirection.getOrientation(1); + case 4: + return ForgeDirection.getOrientation(2); + case 5: + return ForgeDirection.getOrientation(3); + } + + case 2: + switch (side.ordinal()) + { + case 0: + return ForgeDirection.getOrientation(0); + case 1: + return ForgeDirection.getOrientation(1); + case 2: + return ForgeDirection.getOrientation(3); + case 3: + return ForgeDirection.getOrientation(2); + case 4: + return ForgeDirection.getOrientation(5); + case 5: + return ForgeDirection.getOrientation(4); + } + + case 3: + return side; + + case 4: + switch (side.ordinal()) + { + case 0: + return ForgeDirection.getOrientation(0); + case 1: + return ForgeDirection.getOrientation(1); + case 2: + return ForgeDirection.getOrientation(5); + case 3: + return ForgeDirection.getOrientation(4); + case 4: + return ForgeDirection.getOrientation(3); + case 5: + return ForgeDirection.getOrientation(2); + } + + case 5: + switch (side.ordinal()) + { + case 0: + return ForgeDirection.getOrientation(0); + case 1: + return ForgeDirection.getOrientation(1); + case 2: + return ForgeDirection.getOrientation(4); + case 3: + return ForgeDirection.getOrientation(5); + case 4: + return ForgeDirection.getOrientation(2); + case 5: + return ForgeDirection.getOrientation(3); + } + } + + return ForgeDirection.UNKNOWN; + } +} \ No newline at end of file diff --git a/src/common/universalelectricity/electricity/ElectricInfo.java b/src/common/universalelectricity/electricity/ElectricInfo.java new file mode 100644 index 00000000..6652f3d1 --- /dev/null +++ b/src/common/universalelectricity/electricity/ElectricInfo.java @@ -0,0 +1,203 @@ +package universalelectricity.electricity; + +/** + * An easy way to display information on electricity. + * + * @author Calclavia + */ + +public class ElectricInfo +{ + public static enum ElectricUnit + { + AMPERE("Amp", "I"), AMP_HOUR("Amp Hour", "Ah"), VOLTAGE("Volt", "V"), WATT("Watt", "W"), WATT_HOUR("Watt Hour", "Wh"), RESISTANCE("Ohm", "R"), CONDUCTANCE("Siemen", "S"), JOULES("Joule", "J"); + + public String name; + public String symbol; + + private ElectricUnit(String name, String symbol) + { + this.name = name; + this.symbol = symbol; + } + + public String getPlural() + { + return this.name + "s"; + } + } + + public static enum MeasurementUnit + { + MICRO("Micro", "mi", 0.000001), MILLI("Milli", "m", 0.001), KILO("Kilo", "k", 1000), MEGA("Mega", "M", 1000000); + + public String name; + public String symbol; + public double process; + + private MeasurementUnit(String name, String symbol, double process) + { + this.name = name; + this.symbol = symbol; + this.process = process; + } + + public String getName(boolean isSymbol) + { + if (isSymbol) + { + return symbol; + } + else + { + return name; + } + } + + public double process(double value) + { + return value / this.process; + } + } + + public static double getJoules(double watts, double seconds) + { + return watts * seconds; + } + + public static double getJoules(double amps, double voltage, double seconds) + { + return amps * voltage * seconds; + } + + public static double getWattsFromJoules(double joules, double seconds) + { + return joules / seconds; + } + + public static double getAmps(double watts, double voltage) + { + return watts / voltage; + } + + public static double getAmps(double ampHours) + { + return ampHours * 3600; + } + + public static double getAmpsFromWattHours(double wattHours, double voltage) + { + return getWatts(wattHours) / voltage; + } + + public static double getWattHoursFromAmpHours(double ampHours, double voltage) + { + return ampHours * voltage; + } + + public static double getAmpHours(double amps) + { + return amps / 3600; + } + + public static double getWatts(double amps, double voltage) + { + return amps * voltage; + } + + public static double getWatts(double wattHours) + { + return wattHours * 3600; + } + + public static double getWattHours(double watts) + { + return watts / 3600; + } + + public static double getWattHours(double amps, double voltage) + { + return getWattHours(getWatts(amps, voltage)); + } + + public static double getResistance(double amps, double voltage) + { + return voltage / amps; + } + + public static double getConductance(double amps, double voltage) + { + return amps / voltage; + } + + /** + * Displays the unit as text. Works only for positive numbers. + */ + public static String getDisplay(double value, ElectricUnit unit, int significantFigures, boolean isShort) + { + String unitName = unit.name; + + if (isShort) + { + unitName = unit.symbol; + } + else if (value > 1) + { + unitName = unit.getPlural(); + } + + if (value == 0) { return value + " " + unitName; } + + if (value <= MeasurementUnit.MILLI.process) { return roundDecimals(MeasurementUnit.MICRO.process(value), significantFigures) + " " + MeasurementUnit.MICRO.getName(isShort) + unitName; } + + if (value < 1) { return roundDecimals(MeasurementUnit.MILLI.process(value), significantFigures) + " " + MeasurementUnit.MILLI.getName(isShort) + unitName; } + + if (value > MeasurementUnit.KILO.process) { return roundDecimals(MeasurementUnit.KILO.process(value), significantFigures) + " " + MeasurementUnit.KILO.getName(isShort) + unitName; } + + if (value > MeasurementUnit.MEGA.process) { return roundDecimals(MeasurementUnit.MEGA.process(value), significantFigures) + " " + MeasurementUnit.MEGA.getName(isShort) + unitName; } + + return roundDecimals(value, significantFigures) + " " + unitName; + } + + public static String getDisplayShort(double value, ElectricUnit unit) + { + return getDisplay(value, unit, 2, true); + } + + public static String getDisplay(double value, ElectricUnit unit) + { + return getDisplay(value, unit, 2, false); + } + + public static String getDisplaySimple(double value, ElectricUnit unit, int significantFigures) + { + if (value > 1) + { + if (significantFigures < 1) { return (int) value + " " + unit.getPlural(); } + + return roundDecimals(value, significantFigures) + " " + unit.getPlural(); + } + + if (significantFigures < 1) { return (int) value + " " + unit.name; } + + return roundDecimals(value, significantFigures) + " " + unit.name; + } + + /** + * Rounds a number to a specific number place places + * + * @param The + * number + * @return The rounded number + */ + public static double roundDecimals(double d, int significantFigures) + { + int j = (int) (d * Math.pow(10, significantFigures)); + return j / (double) Math.pow(10, significantFigures); + } + + public static double roundDecimals(double d) + { + return roundDecimals(d, 2); + } +} diff --git a/src/common/universalelectricity/electricity/ElectricityManager.java b/src/common/universalelectricity/electricity/ElectricityManager.java new file mode 100644 index 00000000..51335940 --- /dev/null +++ b/src/common/universalelectricity/electricity/ElectricityManager.java @@ -0,0 +1,412 @@ +package universalelectricity.electricity; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import net.minecraft.src.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.core.Vector3; +import universalelectricity.implement.IConductor; +import universalelectricity.implement.IElectricityReceiver; +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.TickType; + +/** + * This class is used to manage electricity + * transferring and flow. It is also used to call + * updates on UE tile entities. + * + * @author Calclavia + * + */ +public class ElectricityManager +{ + /** + * ElectricityManager exists on both client + * and server side. Rely on the server side + * one as it is more accurate! Client side + * only simulates. + */ + public static ElectricityManager instance; + + private List electricityTransferQueue = new ArrayList(); + private List electricityNetworks = new ArrayList(); + + public ElectricityManager() + { + System.out.println("Universal Electricity's Electricity Manager Initiated."); + } + + /** + * Registers a the conductor into the UE + * electricity net. + * + * @param conductor + * - The IConductor tile entity. + */ + public void registerConductor(IConductor newConductor) + { + cleanUpConnections(); + this.electricityNetworks.add(new ElectricityNetwork(newConductor)); + } + + /** + * Merges two connection lines together into + * one. + * + * @param networkA + * - The network to be merged into. + * This network will be kept. + * @param networkB + * - The network to be merged. This + * network will be deleted. + */ + public void mergeConnection(ElectricityNetwork networkA, ElectricityNetwork networkB) + { + if (networkA != networkB) + { + if (networkA != null && networkB != null) + { + networkA.conductors.addAll(networkB.conductors); + networkA.setNetwork(); + this.electricityNetworks.remove(networkB); + networkB = null; + } + else + { + System.err.println("Failed to merge Universal Electricity wire connections!"); + } + } + } + + /** + * Separate one connection line into two + * different ones between two conductors. This + * function does this by resetting all wires + * in the connection line and making them each + * reconnect. + * + * @param conductorA + * - existing conductor + * @param conductorB + * - broken/invalid conductor + */ + public void splitConnection(IConductor conductorA, IConductor conductorB) + { + ElectricityNetwork connection = conductorA.getNetwork(); + + if (connection != null) + { + connection.cleanUpArray(); + + for (IConductor conductor : connection.conductors) + { + conductor.reset(); + } + + for (IConductor conductor : connection.conductors) + { + for (byte i = 0; i < 6; i++) + { + conductor.updateConnectionWithoutSplit(Vector3.getConnectorFromSide(conductor.getWorld(), new Vector3(((TileEntity) conductor).xCoord, ((TileEntity) conductor).yCoord, ((TileEntity) conductor).zCoord), ForgeDirection.getOrientation(i)), ForgeDirection.getOrientation(i)); + } + } + } + else + { + FMLLog.severe("Conductor invalid network while splitting connection!"); + } + } + + /** + * Clean up and remove all useless and invalid + * connections. + */ + public void cleanUpConnections() + { + try + { + for (int i = 0; i < this.electricityNetworks.size(); i++) + { + this.electricityNetworks.get(i).cleanUpArray(); + + if (this.electricityNetworks.get(i).conductors.size() == 0) + { + this.electricityNetworks.remove(i); + } + } + } + catch (Exception e) + { + FMLLog.severe("Failed to clean up wire connections!"); + } + } + + /** + * Produces electricity into a specific wire + * which will be distributed across the + * electricity network. + * + * @param sender + * The machine sending the + * electricity. + * @param targetConductor + * The conductor receiving the + * electricity (or connected to the + * machine). + * @param amps + * The amount of amps this machine + * is sending. + * @param voltage + * The amount of volts this machine + * is sending. + */ + public void produceElectricity(TileEntity sender, IConductor targetConductor, double amps, double voltage) + { + if (targetConductor != null && amps > 0 && voltage > 0) + { + // Find a path between this conductor + // and all connected units and + // try to send the electricity to them + // directly + ElectricityNetwork electricityNetwork = targetConductor.getNetwork(); + + if (electricityNetwork != null) + { + List allElectricUnitsInLine = electricityNetwork.getConnectedReceivers(); + double leftOverAmps = amps; + + for (IConductor conductor : electricityNetwork.conductors) + { + for (byte i = 0; i < conductor.getConnectedBlocks().length; i++) + { + TileEntity tileEntity = conductor.getConnectedBlocks()[i]; + + if (tileEntity != null) + { + if (tileEntity instanceof IElectricityReceiver) + { + IElectricityReceiver receiver = (IElectricityReceiver) tileEntity; + + if (this.getActualWattRequest(receiver) > 0 && receiver.canReceiveFromSide(ForgeDirection.getOrientation(i).getOpposite())) + { + double transferAmps = Math.max(0, Math.min(leftOverAmps, Math.min(amps / allElectricUnitsInLine.size(), ElectricInfo.getAmps(this.getActualWattRequest(receiver), receiver.getVoltage())))); + leftOverAmps -= transferAmps; + + // Calculate + // electricity + // loss + double distance = Vector3.distance(Vector3.get(sender), Vector3.get((TileEntity) receiver)); + double ampsReceived = transferAmps - (transferAmps * transferAmps * targetConductor.getResistance() * distance) / voltage; + double voltsReceived = voltage - (transferAmps * targetConductor.getResistance() * distance); + + this.electricityTransferQueue.add(new ElectricityTransferData(sender, receiver, electricityNetwork, ForgeDirection.getOrientation(i).getOpposite(), ampsReceived, voltsReceived)); + } + } + } + } + } + } + else + { + FMLLog.severe("Conductor not registered to a network!"); + } + } + } + + /** + * Gets the actual watt request of an electric + * receiver accounting all current electricity + * packets qued up for it. + * + * @return - The amount of watts requested. + */ + public double getActualWattRequest(IElectricityReceiver receiver) + { + double wattsRequest = receiver.wattRequest(); + + try + { + for (int i = 0; i < electricityTransferQueue.size(); i++) + { + if (electricityTransferQueue.get(i) != null) + { + if (electricityTransferQueue.get(i).isValid()) + { + if (electricityTransferQueue.get(i).receiver == receiver) + { + wattsRequest -= electricityTransferQueue.get(i).amps * electricityTransferQueue.get(i).voltage; + } + } + } + } + } + catch (Exception e) + { + FMLLog.severe("Failed to get watt request!"); + } + + return Math.max(Math.min(wattsRequest, receiver.wattRequest()), 0); + } + + /** + * Checks if the current connection line needs + * electricity + * + * @return - The amount of joules this + * connection line needs + */ + public double getElectricityRequired(ElectricityNetwork network) + { + double need = 0; + + if (network != null) + { + for (IConductor conductor : network.conductors) + { + for (byte i = 0; i < conductor.getConnectedBlocks().length; i++) + { + TileEntity tileEntity = conductor.getConnectedBlocks()[i]; + + if (tileEntity != null) + { + if (tileEntity instanceof IElectricityReceiver) + { + IElectricityReceiver electricUnit = (IElectricityReceiver) tileEntity; + + if (electricUnit.canReceiveFromSide(ForgeDirection.getOrientation(i).getOpposite())) + { + need += electricUnit.wattRequest(); + } + } + } + } + } + } + + return need; + } + + public double getActualElectricityRequired(ElectricityNetwork network) + { + double need = 0; + + if (network != null) + { + for (IConductor conductor : network.conductors) + { + for (byte i = 0; i < conductor.getConnectedBlocks().length; i++) + { + TileEntity tileEntity = conductor.getConnectedBlocks()[i]; + + if (tileEntity != null) + { + if (tileEntity instanceof IElectricityReceiver) + { + IElectricityReceiver electricUnit = (IElectricityReceiver) tileEntity; + + if (electricUnit.canReceiveFromSide(ForgeDirection.getOrientation(i).getOpposite())) + { + need += this.getActualWattRequest(electricUnit); + } + } + } + } + } + } + + return need; + } + + /** + * This function is called to refresh all + * conductors in the world. + */ + public void refreshConductors() + { + try + { + Iterator it = electricityNetworks.iterator(); + + while (it.hasNext()) + { + ((ElectricityNetwork) it.next()).refreshConductors(); + } + } + catch (Exception e) + { + FMLLog.fine("Failed to refresh conductors."); + } + } + + public void onTick(EnumSet type, Object... tickData) + { + if (type.contains(TickType.WORLD) && !type.contains(TickType.WORLDLOAD)) + { + if (ElectricityManagerTicker.inGameTicks % 40 == 0) + { + this.refreshConductors(); + } + + try + { + HashMap conductorAmpData = new HashMap(); + + for (int i = 0; i < electricityTransferQueue.size(); i++) + { + if (electricityTransferQueue.get(i) != null) + { + if (electricityTransferQueue.get(i).isValid()) + { + double amps = electricityTransferQueue.get(i).amps; + + if (conductorAmpData.containsKey(electricityTransferQueue.get(i).network)) + { + amps += (Double) conductorAmpData.get(electricityTransferQueue.get(i).network); + } + + conductorAmpData.put(electricityTransferQueue.get(i).network, amps); + electricityTransferQueue.get(i).receiver.onReceive(electricityTransferQueue.get(i).sender, electricityTransferQueue.get(i).amps, electricityTransferQueue.get(i).voltage, electricityTransferQueue.get(i).side); + } + } + + electricityTransferQueue.remove(i); + } + + Iterator it = conductorAmpData.entrySet().iterator(); + + while (it.hasNext()) + { + Map.Entry pairs = (Map.Entry) it.next(); + + if (pairs.getKey() != null && pairs.getValue() != null) + { + if (pairs.getKey() instanceof ElectricityNetwork && pairs.getValue() instanceof Double) + { + if (((Double) pairs.getValue()) > ((ElectricityNetwork) pairs.getKey()).getLowestAmpConductor()) + { + ((ElectricityNetwork) pairs.getKey()).onOverCharge(); + } + } + } + + it.remove(); + } + } + catch (Exception e) + { + System.err.println("Failed to transfer electricity to receivers."); + e.printStackTrace(); + } + } + + if (ElectricityManagerTicker.inGameTicks == 0) + { + this.refreshConductors(); + } + } +} \ No newline at end of file diff --git a/src/common/universalelectricity/electricity/ElectricityManagerTicker.java b/src/common/universalelectricity/electricity/ElectricityManagerTicker.java new file mode 100644 index 00000000..91af3872 --- /dev/null +++ b/src/common/universalelectricity/electricity/ElectricityManagerTicker.java @@ -0,0 +1,45 @@ +package universalelectricity.electricity; + +import java.util.EnumSet; + +import cpw.mods.fml.common.ITickHandler; +import cpw.mods.fml.common.TickType; + +public class ElectricityManagerTicker implements ITickHandler +{ + public static long inGameTicks = 0; + + @Override + public void tickStart(EnumSet type, Object... tickData) + { + if (ElectricityManager.instance != null) + { + ElectricityManager.instance.onTick(type, tickData); + } + + inGameTicks++; + + if (inGameTicks >= Long.MAX_VALUE) + { + inGameTicks = 0; + } + } + + @Override + public void tickEnd(EnumSet type, Object... tickData) + { + + } + + @Override + public EnumSet ticks() + { + return EnumSet.of(TickType.WORLD, TickType.WORLDLOAD, TickType.SERVER); + } + + @Override + public String getLabel() + { + return "Electricity Manager"; + } +} diff --git a/src/common/universalelectricity/electricity/ElectricityNetwork.java b/src/common/universalelectricity/electricity/ElectricityNetwork.java new file mode 100644 index 00000000..77106962 --- /dev/null +++ b/src/common/universalelectricity/electricity/ElectricityNetwork.java @@ -0,0 +1,123 @@ +package universalelectricity.electricity; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.src.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.implement.IConductor; +import universalelectricity.implement.IElectricityReceiver; + +public class ElectricityNetwork +{ + public List conductors = new ArrayList(); + + public ElectricityNetwork(IConductor conductor) + { + this.addConductor(conductor); + } + + public void addConductor(IConductor newConductor) + { + this.cleanUpArray(); + + if (!conductors.contains(newConductor)) + { + conductors.add(newConductor); + newConductor.setNetwork(this); + } + } + + /** + * Get only the electric units that can receive electricity from the given + * side. + */ + public List getConnectedReceivers() + { + this.cleanUpArray(); + List returnArray = new ArrayList(); + + for (IConductor conductor : conductors) + { + for (byte i = 0; i < conductor.getConnectedBlocks().length; i++) + { + TileEntity tileEntity = conductor.getConnectedBlocks()[i]; + + if (tileEntity != null) + { + if (tileEntity instanceof IElectricityReceiver) + { + if (!returnArray.contains((IElectricityReceiver) tileEntity) && ((IElectricityReceiver) tileEntity).canReceiveFromSide(ForgeDirection.getOrientation(i).getOpposite())) + { + returnArray.add((IElectricityReceiver) tileEntity); + } + } + } + } + } + + return returnArray; + } + + public void cleanUpArray() + { + for (int i = 0; i < conductors.size(); i++) + { + if (conductors.get(i) == null) + { + conductors.remove(i); + } + else if (((TileEntity) conductors.get(i)).isInvalid()) + { + conductors.remove(i); + } + } + } + + public void setNetwork() + { + this.cleanUpArray(); + + for (IConductor conductor : this.conductors) + { + conductor.setNetwork(this); + } + } + + public void onOverCharge() + { + this.cleanUpArray(); + + for (int i = 0; i < conductors.size(); i++) + { + conductors.get(i).onOverCharge(); + } + } + + public double getLowestAmpConductor() + { + double lowestAmp = 0; + + for (IConductor conductor : conductors) + { + if (lowestAmp == 0 || conductor.getMaxAmps() < lowestAmp) + { + lowestAmp = conductor.getMaxAmps(); + } + } + + return lowestAmp; + } + + /** + * This function is called to refresh all conductors in this network + */ + public void refreshConductors() + { + for (int j = 0; j < this.conductors.size(); j++) + { + IConductor conductor = this.conductors.get(j); + conductor.refreshConnectedBlocks(); + } + } +} diff --git a/src/common/universalelectricity/electricity/ElectricityTransferData.java b/src/common/universalelectricity/electricity/ElectricityTransferData.java new file mode 100644 index 00000000..52ba7231 --- /dev/null +++ b/src/common/universalelectricity/electricity/ElectricityTransferData.java @@ -0,0 +1,42 @@ +package universalelectricity.electricity; + +import net.minecraft.src.TileEntity; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.implement.IElectricityReceiver; + +public class ElectricityTransferData +{ + public TileEntity sender; + public IElectricityReceiver receiver; + public ElectricityNetwork network; + public double amps; + public double voltage; + public ForgeDirection side; + + /** + * @param sender + * - Tile that's sending electricity. + * @param receiver + * - Receiver that's receiving electricity + * @param conductor + * - Conductor that is conducting the electricity + * @param side + * - + * @param amps + * @param voltage + */ + public ElectricityTransferData(TileEntity sender, IElectricityReceiver receiver, ElectricityNetwork network, ForgeDirection side, double amps, double voltage) + { + this.sender = sender; + this.receiver = receiver; + this.network = network; + this.side = side; + this.amps = amps; + this.voltage = voltage; + } + + public boolean isValid() + { + return this.sender != null && this.receiver != null && this.network != null && this.amps > 0 && this.voltage > 0; + } +} diff --git a/src/common/universalelectricity/implement/IConductor.java b/src/common/universalelectricity/implement/IConductor.java new file mode 100644 index 00000000..afb0a526 --- /dev/null +++ b/src/common/universalelectricity/implement/IConductor.java @@ -0,0 +1,71 @@ +package universalelectricity.implement; + +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.electricity.ElectricityNetwork; + +/** + * Must be applied to all tile entities that are conductors. + * + * @author Calclavia + * + */ +public interface IConductor extends IConnector +{ + /** + * The electrical network this conductor is on. + */ + public ElectricityNetwork getNetwork(); + + public void setNetwork(ElectricityNetwork network); + + /** + * The UE tile entities that this conductor is connected to. + * + * @return + */ + public TileEntity[] getConnectedBlocks(); + + /** + * Gets the resistance of the conductor. Used to calculate energy loss. A + * higher resistance means a higher energy loss. + * + * @return The amount of Ohm's of resistance. + */ + public double getResistance(); + + /** + * The maximum amount of amps this conductor can handle before melting down. + * This is calculating PER TICK! + * + * @return The amount of amps in volts + */ + public double getMaxAmps(); + + /** + * Called when the electricity passing through exceeds the maximum voltage. + */ + public void onOverCharge(); + + /** + * Resets the conductor and recalculate connection IDs again + */ + public void reset(); + + public World getWorld(); + + /** + * Adds a connection between this conductor and a UE unit + * + * @param tileEntity + * - Must be either a producer, consumer or a conductor + * @param side + * - side in which the connection is coming from + */ + public void updateConnection(TileEntity tileEntity, ForgeDirection side); + + public void updateConnectionWithoutSplit(TileEntity connectorFromSide, ForgeDirection orientation); + + public void refreshConnectedBlocks(); +} diff --git a/src/common/universalelectricity/implement/IConnector.java b/src/common/universalelectricity/implement/IConnector.java new file mode 100644 index 00000000..8979569b --- /dev/null +++ b/src/common/universalelectricity/implement/IConnector.java @@ -0,0 +1,21 @@ +package universalelectricity.implement; + +import net.minecraftforge.common.ForgeDirection; + +/** + * Applied to TileEntities that can connect to UE wires. + * + * @author Calclavia + * + */ +public interface IConnector +{ + /** + * Can this tile entity visually connect to a wire on this specific side? + * + * @param side + * - The side in which the connection is coming from. + * @return - True if so. + */ + public boolean canConnect(ForgeDirection side); +} diff --git a/src/common/universalelectricity/implement/IDisableable.java b/src/common/universalelectricity/implement/IDisableable.java new file mode 100644 index 00000000..535782a0 --- /dev/null +++ b/src/common/universalelectricity/implement/IDisableable.java @@ -0,0 +1,26 @@ +package universalelectricity.implement; + +/** + * This class should be applied to all tile entities (mainly machines) that can + * be disabled (by things like EMP, short circuit etc.). + * + * @author Calclavia + * + */ +public interface IDisableable +{ + /** + * This is called when the tile entity is to be disabled. + * + * @param duration + * - The duration of the disable in ticks. + */ + public void onDisable(int duration); + + /** + * Called to see if this tile entity is disabled. + * + * @return True if the tile entity is disabled. + */ + public boolean isDisabled(); +} diff --git a/src/common/universalelectricity/implement/IElectricityProducer.java b/src/common/universalelectricity/implement/IElectricityProducer.java new file mode 100644 index 00000000..80cbb5bc --- /dev/null +++ b/src/common/universalelectricity/implement/IElectricityProducer.java @@ -0,0 +1,20 @@ +package universalelectricity.implement; + +import net.minecraftforge.common.ForgeDirection; + +/** + * Applied to tile entities that can produce electricity + * + * @author Calclavia + */ +public interface IElectricityProducer extends IConnector, IDisableable, IVoltage +{ + /** + * Can this machine visually connect to a wire on this specific side? + * + * @param side + * . 0-5 byte + * @return - True if so. + */ + public boolean canConnect(ForgeDirection side); +} diff --git a/src/common/universalelectricity/implement/IElectricityReceiver.java b/src/common/universalelectricity/implement/IElectricityReceiver.java new file mode 100644 index 00000000..531d30a4 --- /dev/null +++ b/src/common/universalelectricity/implement/IElectricityReceiver.java @@ -0,0 +1,41 @@ +package universalelectricity.implement; + +import net.minecraft.src.TileEntity; +import net.minecraftforge.common.ForgeDirection; + +/** + * The IElectricityReceiver interface is an interface that must be applied to + * all tile entities that can input or output electricity. + * + * @author Calclavia + * + */ +public interface IElectricityReceiver extends IDisableable, IConnector, IVoltage +{ + /** + * Called every tick on this machine. + * + * @param amps + * - Amount of amps this electric unit is receiving. + * @param voltage + * - The voltage of the electricity sent. If more than one packet + * is being sent to you in this update, the highest voltage will + * override. + * @param side + * - The side of the block in which the electricity is coming + * from. + */ + public void onReceive(TileEntity sender, double amps, double voltage, ForgeDirection side); + + /** + * How many watts does this electrical unit need this tick? Recommended for + * you to return the max electricity storage of this machine (if there is + * one). + */ + public double wattRequest(); + + /** + * Can this unit receive electricity from this specific side? + */ + public boolean canReceiveFromSide(ForgeDirection side); +} \ No newline at end of file diff --git a/src/common/universalelectricity/implement/IItemElectric.java b/src/common/universalelectricity/implement/IItemElectric.java new file mode 100644 index 00000000..032d8e1d --- /dev/null +++ b/src/common/universalelectricity/implement/IItemElectric.java @@ -0,0 +1,33 @@ +package universalelectricity.implement; + +import net.minecraft.src.ItemStack; + +public interface IItemElectric extends IJouleStorage, IVoltage +{ + /** + * Called when this item receives electricity. + */ + public double onReceive(double amps, double voltage, ItemStack itemStack); + + /** + * Called when something requests electricity from this item. + * + * @return - The amount of given joules + */ + public double onUse(double joulesNeeded, ItemStack itemStack); + + /** + * @return Returns true or false if this consumer can receive electricity at + * this given tick or moment. + */ + public boolean canReceiveElectricity(); + + /** + * Can this item give out electricity when placed in an tile entity? + * Electric items like batteries should be able to produce electricity (if + * they are rechargeable). + * + * @return - True or False. + */ + public boolean canProduceElectricity(); +} diff --git a/src/common/universalelectricity/implement/IJouleStorage.java b/src/common/universalelectricity/implement/IJouleStorage.java new file mode 100644 index 00000000..244f7756 --- /dev/null +++ b/src/common/universalelectricity/implement/IJouleStorage.java @@ -0,0 +1,25 @@ +package universalelectricity.implement; + +/** + * This interface is to be applied to all tile entities which stores energy + * within them. + * + * @author Calclavia + */ +public interface IJouleStorage +{ + /** + * Returns the amount of joules this unit has stored. + */ + public double getJoules(Object... data); + + /** + * Sets the amount of joules this unit has stored. + */ + public void setJoules(double wattHours, Object... data); + + /** + * Gets the maximum amount of joules this unit can store. + */ + public double getMaxJoules(); +} diff --git a/src/common/universalelectricity/implement/IRedstoneProvider.java b/src/common/universalelectricity/implement/IRedstoneProvider.java new file mode 100644 index 00000000..1e87ff12 --- /dev/null +++ b/src/common/universalelectricity/implement/IRedstoneProvider.java @@ -0,0 +1,14 @@ +package universalelectricity.implement; + +/** + * This should be applied on tile entities that can provide redstone power + * + * @author Henry + * + */ +public interface IRedstoneProvider +{ + public boolean isPoweringTo(byte side); + + public boolean isIndirectlyPoweringTo(byte side); +} diff --git a/src/common/universalelectricity/implement/IRedstoneReceptor.java b/src/common/universalelectricity/implement/IRedstoneReceptor.java new file mode 100644 index 00000000..41a0cee9 --- /dev/null +++ b/src/common/universalelectricity/implement/IRedstoneReceptor.java @@ -0,0 +1,21 @@ +package universalelectricity.implement; + +/** + * OPTIONAL This interface should be applied onto all tile entities that needs + * to receive redstone power. Look at TileEntityBatteryBox for reference. + * + * @author Calclavia + * + */ +public interface IRedstoneReceptor +{ + /** + * Called when the block is powered on by redstone + */ + public void onPowerOn(); + + /** + * Called when the block is powered off by redstone + */ + public void onPowerOff(); +} diff --git a/src/common/universalelectricity/implement/IRotatable.java b/src/common/universalelectricity/implement/IRotatable.java new file mode 100644 index 00000000..04b4268b --- /dev/null +++ b/src/common/universalelectricity/implement/IRotatable.java @@ -0,0 +1,33 @@ +package universalelectricity.implement; + +import net.minecraftforge.common.ForgeDirection; + +/** + * This interface should be applied onto all tile entities that are + * rotatable. This interface however is optional and you do not need it for your + * add-on to function. It just makes things easier for you to code. + * + * @author Calclavia + * + */ + +public interface IRotatable +{ + /** + * Gets the facing direction of the tile entity. Always returns the front + * side of the tile entity. + * + * @return The facing side from 0-5 The full list of which side the number + * represents is in the UniversalElectricity class. + */ + public ForgeDirection getDirection(); + + /** + * Sets the facing direction of the tile entity. + * + * @param facingDirection + * - A direction from 0-5. The full list of which side the number + * represents is in the UniversalElectricity class. + */ + public void setDirection(ForgeDirection facingDirection); +} diff --git a/src/common/universalelectricity/implement/ITier.java b/src/common/universalelectricity/implement/ITier.java new file mode 100644 index 00000000..f3ae19fe --- /dev/null +++ b/src/common/universalelectricity/implement/ITier.java @@ -0,0 +1,25 @@ +package universalelectricity.implement; + +/** + * This interface should be applied to all things that has a tier/level. + * + * @author Calclavia + * + */ +public interface ITier +{ + /** + * Gets the tier of this object + * + * @return - The tier + */ + public int getTier(); + + /** + * Sets the tier of the object + * + * @param tier + * - The tier to be set + */ + public void setTier(int tier); +} diff --git a/src/common/universalelectricity/implement/IVoltage.java b/src/common/universalelectricity/implement/IVoltage.java new file mode 100644 index 00000000..5d95d0d1 --- /dev/null +++ b/src/common/universalelectricity/implement/IVoltage.java @@ -0,0 +1,15 @@ +package universalelectricity.implement; + +/** + * Applies to all objects that has a voltage. + * @author Calclavia + * + */ +public interface IVoltage +{ + /** + * Gets the voltage of this object. + * @return The amount of volts. E.g 120v or 240v + */ + public double getVoltage(); +} diff --git a/src/common/universalelectricity/implement/UEDamageSource.java b/src/common/universalelectricity/implement/UEDamageSource.java new file mode 100644 index 00000000..35cf8314 --- /dev/null +++ b/src/common/universalelectricity/implement/UEDamageSource.java @@ -0,0 +1,57 @@ +package universalelectricity.implement; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.src.DamageSource; +import cpw.mods.fml.common.registry.LanguageRegistry; + +public class UEDamageSource extends DamageSource +{ + public static final List damageSources = new ArrayList(); + + /** + * Use this damage source for all types of electrical attacks. + */ + public static final UEDamageSource electrocution = (UEDamageSource) new UEDamageSource("electrocution", "%1$s got electrocuted!").setDamageBypassesArmor(); + + public String deathMessage; + + public UEDamageSource(String damageType) + { + super(damageType); + damageSources.add(this); + } + + public UEDamageSource(String damageType, String deathMessage) + { + this(damageType); + this.setDeathMessage(deathMessage); + } + + public UEDamageSource setDeathMessage(String deathMessage) + { + this.deathMessage = deathMessage; + return this; + } + + public DamageSource setDamageBypassesArmor() + { + return super.setDamageBypassesArmor(); + } + + public DamageSource setDamageAllowedInCreativeMode() + { + return super.setDamageAllowedInCreativeMode(); + } + + public DamageSource setFireDamage() + { + return super.setFireDamage(); + } + + public void registerDeathMessage() + { + LanguageRegistry.instance().addStringLocalization("death." + this.damageType, this.deathMessage); + } +} diff --git a/src/common/universalelectricity/prefab/BlockConductor.java b/src/common/universalelectricity/prefab/BlockConductor.java new file mode 100644 index 00000000..3852281d --- /dev/null +++ b/src/common/universalelectricity/prefab/BlockConductor.java @@ -0,0 +1,55 @@ +package universalelectricity.prefab; + +import net.minecraft.src.BlockContainer; +import net.minecraft.src.Material; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import universalelectricity.implement.IConductor; + +public abstract class BlockConductor extends BlockContainer +{ + public BlockConductor(int id, Material material) + { + super(id, material); + } + + /** + * Called whenever the block is added into the world. Args: world, x, y, z + */ + @Override + public void onBlockAdded(World world, int x, int y, int z) + { + super.onBlockAdded(world, x, y, z); + + TileEntity tileEntity = world.getBlockTileEntity(x, y, z); + + if(tileEntity != null) + { + if(tileEntity instanceof IConductor) + { + ((IConductor)tileEntity).refreshConnectedBlocks(); + } + } + } + + /** + * Lets the block know when one of its neighbor changes. Doesn't know which + * neighbor changed (coordinates passed are their own) Args: x, y, z, + * neighbor blockID + */ + @Override + public void onNeighborBlockChange(World world, int x, int y, int z, int blockID) + { + TileEntity tileEntity = world.getBlockTileEntity(x, y, z); + + if(tileEntity != null) + { + if(tileEntity instanceof IConductor) + { + ((IConductor)tileEntity).refreshConnectedBlocks(); + } + } + + world.markBlockNeedsUpdate(x, y, z); + } +} diff --git a/src/common/universalelectricity/prefab/BlockMachine.java b/src/common/universalelectricity/prefab/BlockMachine.java new file mode 100644 index 00000000..75e393ee --- /dev/null +++ b/src/common/universalelectricity/prefab/BlockMachine.java @@ -0,0 +1,226 @@ +package universalelectricity.prefab; + +import java.util.Random; + +import net.minecraft.src.BlockContainer; +import net.minecraft.src.CreativeTabs; +import net.minecraft.src.EntityItem; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.IInventory; +import net.minecraft.src.ItemStack; +import net.minecraft.src.Material; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import universalelectricity.implement.IItemElectric; +import buildcraft.api.tools.IToolWrench; + +/** + * A block you may extend from to create your machine blocks! You do not have to + * extend from this block if you do not want to. It's optional but it comes with + * some useful functions that will make coding easier for you. + */ +public abstract class BlockMachine extends BlockContainer +{ + public BlockMachine(String name, int id, Material material) + { + super(id, material); + this.setBlockName(name); + this.setHardness(0.5F); + } + + public BlockMachine(String name, int id, Material material, CreativeTabs creativeTab) + { + this(name, id, material); + this.setCreativeTab(creativeTab); + } + + @Override + public int damageDropped(int metadata) + { + return metadata; + } + + /** + * Returns the quantity of items to drop on block destruction. + */ + @Override + public int quantityDropped(Random par1Random) + { + return 1; + } + + /** + * Returns the ID of the items to drop on destruction. + */ + @Override + public int idDropped(int par1, Random par2Random, int par3) + { + return this.blockID; + } + + /** + * DO NOT OVERRIDE THIS FUNCTION! Called when the block is right clicked by + * the player. This modified version detects electric items and wrench + * actions on your machine block. Do not override this function. Use + * machineActivated instead! (It does the same thing) + */ + @Override + public boolean onBlockActivated(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) + { + int metadata = par1World.getBlockMetadata(x, y, z); + + /** + * Check if the player is holding a wrench or an electric item. If so, + * do not open the GUI. + */ + if (par5EntityPlayer.inventory.getCurrentItem() != null) + { + if (par5EntityPlayer.inventory.getCurrentItem().getItem() instanceof IToolWrench) + { + par1World.notifyBlocksOfNeighborChange(x, y, z, this.blockID); + ((IToolWrench) par5EntityPlayer.inventory.getCurrentItem().getItem()).wrenchUsed(par5EntityPlayer, x, y, z); + + if (par5EntityPlayer.isSneaking()) + { + return this.onSneakUseWrench(par1World, x, y, z, par5EntityPlayer); + } + else + { + return this.onUseWrench(par1World, x, y, z, par5EntityPlayer); + } + } + else if (par5EntityPlayer.inventory.getCurrentItem().getItem() instanceof IItemElectric) + { + if (this.onUseElectricItem(par1World, x, y, z, par5EntityPlayer)) { return true; } + } + } + + if (par5EntityPlayer.isSneaking()) + { + return this.onSneakMachineActivated(par1World, x, y, z, par5EntityPlayer); + } + else + { + return this.onMachineActivated(par1World, x, y, z, par5EntityPlayer); + } + } + + /** + * Called when the machine is right clicked by the player + * + * @return True if something happens + */ + public boolean onMachineActivated(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + return false; + } + + /** + * Called when the machine is right clicked by the player while sneaking + * (shift clicking) + * + * @return True if something happens + */ + public boolean onSneakMachineActivated(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + return false; + } + + /** + * Called when a player uses an electric item on the machine + * + * @return True if some happens + */ + public boolean onUseElectricItem(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + return false; + } + + /** + * Called when a player uses a wrench on the machine + * + * @return True if some happens + */ + public boolean onUseWrench(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + return false; + } + + /** + * Called when a player uses a wrench on the machine while sneaking + * + * @return True if some happens + */ + public boolean onSneakUseWrench(World par1World, int x, int y, int z, EntityPlayer par5EntityPlayer) + { + return this.onUseWrench(par1World, x, y, z, par5EntityPlayer); + } + + /** + * Returns the TileEntity used by this block. You should use the metadata + * sensitive version of this to get the maximum optimization! + */ + @Override + public TileEntity createNewTileEntity(World var1) + { + return null; + } + + /** + * Override this if you don't need it. This will eject all items out of this + * machine if it has an inventory + */ + @Override + public void breakBlock(World par1World, int x, int y, int z, int par5, int par6) + { + TileEntity tileEntity = par1World.getBlockTileEntity(x, y, z); + + if (tileEntity != null) + { + if (tileEntity instanceof IInventory) + { + IInventory inventory = (IInventory) tileEntity; + + for (int var6 = 0; var6 < inventory.getSizeInventory(); ++var6) + { + ItemStack var7 = inventory.getStackInSlot(var6); + + if (var7 != null) + { + Random random = new Random(); + float var8 = random.nextFloat() * 0.8F + 0.1F; + float var9 = random.nextFloat() * 0.8F + 0.1F; + float var10 = random.nextFloat() * 0.8F + 0.1F; + + while (var7.stackSize > 0) + { + int var11 = random.nextInt(21) + 10; + + if (var11 > var7.stackSize) + { + var11 = var7.stackSize; + } + + var7.stackSize -= var11; + EntityItem var12 = new EntityItem(par1World, (x + var8), (y + var9), (z + var10), new ItemStack(var7.itemID, var11, var7.getItemDamage())); + + if (var7.hasTagCompound()) + { + var12.item.setTagCompound((NBTTagCompound) var7.getTagCompound().copy()); + } + + float var13 = 0.05F; + var12.motionX = ((float) random.nextGaussian() * var13); + var12.motionY = ((float) random.nextGaussian() * var13 + 0.2F); + var12.motionZ = ((float) random.nextGaussian() * var13); + par1World.spawnEntityInWorld(var12); + } + } + } + } + } + + super.breakBlock(par1World, x, y, z, par5, par6); + } +} diff --git a/src/common/universalelectricity/prefab/ItemElectric.java b/src/common/universalelectricity/prefab/ItemElectric.java new file mode 100644 index 00000000..45c79054 --- /dev/null +++ b/src/common/universalelectricity/prefab/ItemElectric.java @@ -0,0 +1,207 @@ +package universalelectricity.prefab; + +import java.util.List; + +import net.minecraft.src.CreativeTabs; +import net.minecraft.src.Entity; +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import net.minecraft.src.NBTTagCompound; +import net.minecraft.src.NBTTagFloat; +import net.minecraft.src.World; +import universalelectricity.electricity.ElectricInfo; +import universalelectricity.electricity.ElectricInfo.ElectricUnit; +import universalelectricity.implement.IItemElectric; + +/** + * Extend from this class if your item requires electricity or to be charged. + * Optionally, you can implement IItemElectric instead. + * + * @author Calclavia + * + */ +public abstract class ItemElectric extends Item implements IItemElectric +{ + public ItemElectric(int id, CreativeTabs tabs) + { + super(id); + this.setMaxStackSize(1); + this.setMaxDamage((int) this.getMaxJoules()); + this.setNoRepair(); + this.setCreativeTab(tabs); + } + + public ItemElectric(int id) + { + this(id, CreativeTabs.tabTools); + } + + /** + * Allows items to add custom lines of information to the mouseover + * description. If you want to add more information to your item, you can + * super.addInformation() to keep the electiricty info in the item info bar. + */ + @Override + public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4) + { + String color = ""; + double joules = this.getJoules(par1ItemStack); + + if (joules <= this.getMaxJoules() / 3) + { + color = "\u00a74"; + } + else if (joules > this.getMaxJoules() * 2 / 3) + { + color = "\u00a72"; + } + else + { + color = "\u00a76"; + } + + par3List.add(color + ElectricInfo.getDisplay(joules, ElectricUnit.JOULES) + " - " + Math.round((joules / this.getMaxJoules()) * 100) + "%"); + } + + /** + * Make sure you super this method! + */ + @Override + public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5) + { + // Makes sure the damage is set correctly for this electric item! + ItemElectric item = ((ItemElectric) par1ItemStack.getItem()); + item.setJoules(item.getJoules(par1ItemStack), par1ItemStack); + } + + /** + * Makes sure the item is uncharged when it is crafted and not charged. + * Change this if you do not want this to happen! + */ + @Override + public void onCreated(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) + { + par1ItemStack = this.getUncharged(); + } + + @Override + public double onReceive(double amps, double voltage, ItemStack itemStack) + { + double rejectedElectricity = Math.max((this.getJoules(itemStack) + ElectricInfo.getJoules(amps, voltage, 1)) - this.getMaxJoules(), 0); + this.setJoules(this.getJoules(itemStack) + ElectricInfo.getJoules(amps, voltage, 1) - rejectedElectricity, itemStack); + return rejectedElectricity; + } + + @Override + public double onUse(double joulesNeeded, ItemStack itemStack) + { + double electricityToUse = Math.min(this.getJoules(itemStack), joulesNeeded); + this.setJoules(this.getJoules(itemStack) - electricityToUse, itemStack); + return electricityToUse; + } + + public boolean canReceiveElectricity() + { + return true; + } + + public boolean canProduceElectricity() + { + return false; + } + + /** + * This function sets the electriicty. Do not directly call this function. + * Try to use onReceiveElectricity or onUseElectricity instead. + * + * @param wattHours + * - The amount of electricity in joules + */ + @Override + public void setJoules(double wattHours, Object... data) + { + if (data[0] instanceof ItemStack) + { + ItemStack itemStack = (ItemStack) data[0]; + + // Saves the frequency in the itemstack + if (itemStack.stackTagCompound == null) + { + itemStack.setTagCompound(new NBTTagCompound()); + } + + double electricityStored = Math.max(Math.min(wattHours, this.getMaxJoules()), 0); + itemStack.stackTagCompound.setDouble("electricity", electricityStored); + itemStack.setItemDamage((int) (getMaxJoules() - electricityStored)); + } + } + + /** + * This function is called to get the electricity stored in this item + * + * @return - The amount of electricity stored in watts + */ + @Override + public double getJoules(Object... data) + { + if (data[0] instanceof ItemStack) + { + ItemStack itemStack = (ItemStack) data[0]; + + if (itemStack.stackTagCompound == null) { return 0; } + double electricityStored = 0; + if (itemStack.stackTagCompound.getTag("electricity") instanceof NBTTagFloat) + { + electricityStored = itemStack.stackTagCompound.getFloat("electricity"); + } + else + { + electricityStored = itemStack.stackTagCompound.getDouble("electricity"); + } + itemStack.setItemDamage((int) (getMaxJoules() - electricityStored)); + return electricityStored; + } + + return -1; + } + + /** + * Returns an uncharged version of the electric item. Use this if you want + * the crafting recipe to use a charged version of the electric item instead + * of an empty version of the electric item + * + * @return The ItemStack of a fully charged electric item + */ + public ItemStack getUncharged() + { + ItemStack chargedItem = new ItemStack(this); + chargedItem.setItemDamage((int) this.getMaxJoules()); + return chargedItem; + } + + public static ItemStack getUncharged(ItemStack itemStack) + { + if(itemStack.getItem() instanceof IItemElectric) + { + ItemStack chargedItem = itemStack.copy(); + chargedItem.setItemDamage((int)((IItemElectric)itemStack.getItem()).getMaxJoules()); + return chargedItem; + } + + return null; + } + + @Override + public void getSubItems(int par1, CreativeTabs par2CreativeTabs, List par3List) + { + // Add an uncharged version of the electric item + ItemStack unchargedItem = new ItemStack(this, 1); + unchargedItem.setItemDamage((int) this.getMaxJoules()); + par3List.add(unchargedItem); + // Add an electric item to the creative list that is fully charged + ItemStack chargedItem = new ItemStack(this, 1); + this.setJoules(((IItemElectric) chargedItem.getItem()).getMaxJoules(), chargedItem); + par3List.add(chargedItem); + } +} diff --git a/src/common/universalelectricity/prefab/RecipeHelper.java b/src/common/universalelectricity/prefab/RecipeHelper.java new file mode 100644 index 00000000..62a13cc1 --- /dev/null +++ b/src/common/universalelectricity/prefab/RecipeHelper.java @@ -0,0 +1,96 @@ +package universalelectricity.prefab; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.src.CraftingManager; +import net.minecraft.src.IRecipe; +import net.minecraft.src.ItemStack; +import net.minecraftforge.common.Configuration; +import universalelectricity.core.UEConfig; +import cpw.mods.fml.common.registry.GameRegistry; + +/** + * This class is used to replace recipes that are already added in the existing + * recipe pool for crafting and smelting. All recipe functions take account of + * the Forge Ore Dictionary. It also includes some recipe helper functions to + * shorten some of your function calls. + * + * @author Calclavia + * + */ +public class RecipeHelper +{ + public static List getRecipesByOutput(ItemStack output) + { + List list = new ArrayList(); + + for (Object obj : CraftingManager.getInstance().getRecipeList()) + { + if (obj instanceof IRecipe) + { + if (((IRecipe) obj).getRecipeOutput() == output) + { + list.add((IRecipe)obj); + } + } + } + + return list; + } + + public static boolean replaceRecipe(IRecipe recipe, IRecipe newRecipe) + { + for (Object obj : CraftingManager.getInstance().getRecipeList()) + { + if (obj instanceof IRecipe) + { + if (((IRecipe) obj).equals(recipe) || obj == recipe) + { + CraftingManager.getInstance().getRecipeList().remove(obj); + CraftingManager.getInstance().getRecipeList().add(newRecipe); + return true; + } + } + } + + return false; + } + + public static boolean removeRecipe(IRecipe recipe) + { + for (Object obj : CraftingManager.getInstance().getRecipeList()) + { + if (obj instanceof IRecipe) + { + if (((IRecipe) obj).equals(recipe) || obj == recipe) + { + CraftingManager.getInstance().getRecipeList().remove(obj); + return true; + } + } + } + + return false; + } + + /** + * Use this function if you want to check if the recipe is allowed in the + * configuration file. + */ + public static void addRecipe(IRecipe recipe, String name, Configuration config, boolean defaultBoolean) + { + if (config != null) + { + if (UEConfig.getConfigData(config, "Allow " + name + " Crafting", defaultBoolean)) + { + GameRegistry.addRecipe(recipe); + } + } + } + + public static void addRecipe(IRecipe recipe, Configuration config, boolean defaultBoolean) + { + addRecipe(recipe, recipe.getRecipeOutput().getItemName(), config, defaultBoolean); + } +} diff --git a/src/common/universalelectricity/prefab/SlotElectricItem.java b/src/common/universalelectricity/prefab/SlotElectricItem.java new file mode 100644 index 00000000..3d8b7569 --- /dev/null +++ b/src/common/universalelectricity/prefab/SlotElectricItem.java @@ -0,0 +1,31 @@ +package universalelectricity.prefab; + +import net.minecraft.src.IInventory; +import net.minecraft.src.ItemStack; +import net.minecraft.src.Slot; +import universalelectricity.implement.IItemElectric; + +/** + * This slot should be used by any container that needs the slot for an electric + * items only. + * + * @author Calclavia + * + */ +public class SlotElectricItem extends Slot +{ + public SlotElectricItem(IInventory par2IInventory, int par3, int par4, int par5) + { + super(par2IInventory, par3, par4, par5); + } + + /** + * Check if the stack is a valid item for this slot. Always true beside for + * the armor slots. + */ + @Override + public boolean isItemValid(ItemStack par1ItemStack) + { + return par1ItemStack.getItem() instanceof IItemElectric; + } +} diff --git a/src/common/universalelectricity/prefab/TileEntityAdvanced.java b/src/common/universalelectricity/prefab/TileEntityAdvanced.java new file mode 100644 index 00000000..a9bf8420 --- /dev/null +++ b/src/common/universalelectricity/prefab/TileEntityAdvanced.java @@ -0,0 +1,60 @@ +package universalelectricity.prefab; + +import net.minecraft.src.Block; +import net.minecraft.src.TileEntity; + +/** + * A TileEntity with some pre-added functionalities. + * + * @author Calclavia + * + */ +public abstract class TileEntityAdvanced extends TileEntity +{ + protected long ticks = 0; + + @Override + public void updateEntity() + { + if (this.ticks == 0) + { + this.initiate(); + } + + if (this.ticks >= Long.MAX_VALUE) + { + this.ticks = 1; + } + + this.ticks++; + } + + /** + * Called on the TileEntity's first tick. + */ + protected void initiate() + { + } + + @Override + public int getBlockMetadata() + { + if (this.blockMetadata == -1) + { + this.blockMetadata = this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord); + } + + return this.blockMetadata; + } + + @Override + public Block getBlockType() + { + if (this.blockType == null) + { + this.blockType = Block.blocksList[this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord)]; + } + + return this.blockType; + } +} diff --git a/src/common/universalelectricity/prefab/TileEntityDisableable.java b/src/common/universalelectricity/prefab/TileEntityDisableable.java new file mode 100644 index 00000000..fa45746b --- /dev/null +++ b/src/common/universalelectricity/prefab/TileEntityDisableable.java @@ -0,0 +1,47 @@ +package universalelectricity.prefab; + +import universalelectricity.implement.IDisableable; + +/** + * An easier way to implement the methods from IElectricityDisableable with + * default values set. + * + * @author Calclavia + */ +public abstract class TileEntityDisableable extends TileEntityAdvanced implements IDisableable +{ + protected int disabledTicks = 0; + + @Override + public void updateEntity() + { + super.updateEntity(); + + if (this.disabledTicks > 0) + { + this.disabledTicks--; + this.whileDisable(); + return; + } + } + + /** + * Called every tick while this tile entity is disabled. + */ + protected void whileDisable() + { + + } + + @Override + public void onDisable(int duration) + { + this.disabledTicks = duration; + } + + @Override + public boolean isDisabled() + { + return this.disabledTicks > 0; + } +} diff --git a/src/common/universalelectricity/prefab/TileEntityElectricityReceiver.java b/src/common/universalelectricity/prefab/TileEntityElectricityReceiver.java new file mode 100644 index 00000000..76ff0aa9 --- /dev/null +++ b/src/common/universalelectricity/prefab/TileEntityElectricityReceiver.java @@ -0,0 +1,36 @@ +package universalelectricity.prefab; + +import net.minecraftforge.common.ForgeDirection; +import universalelectricity.implement.IElectricityReceiver; + +/** + * An easier way to implement the methods from IElectricityReceiver with default + * values set. + * + * @author Calclavia + */ +public abstract class TileEntityElectricityReceiver extends TileEntityDisableable implements IElectricityReceiver +{ + public TileEntityElectricityReceiver() + { + super(); + } + + @Override + public void updateEntity() + { + super.updateEntity(); + } + + @Override + public boolean canConnect(ForgeDirection side) + { + return this.canReceiveFromSide(side); + } + + @Override + public double getVoltage() + { + return 120; + } +} diff --git a/src/common/universalelectricity/prefab/network/IPacketReceiver.java b/src/common/universalelectricity/prefab/network/IPacketReceiver.java new file mode 100644 index 00000000..bf39ea4d --- /dev/null +++ b/src/common/universalelectricity/prefab/network/IPacketReceiver.java @@ -0,0 +1,15 @@ +package universalelectricity.prefab.network; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.INetworkManager; +import net.minecraft.src.Packet250CustomPayload; + +import com.google.common.io.ByteArrayDataInput; + +public interface IPacketReceiver +{ + /** + * Sends some data to the tile entity. + */ + public void handlePacketData(INetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream); +} diff --git a/src/common/universalelectricity/prefab/network/PacketManager.java b/src/common/universalelectricity/prefab/network/PacketManager.java new file mode 100644 index 00000000..0e3f6889 --- /dev/null +++ b/src/common/universalelectricity/prefab/network/PacketManager.java @@ -0,0 +1,266 @@ +package universalelectricity.prefab.network; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.src.EntityPlayer; +import net.minecraft.src.INetworkManager; +import net.minecraft.src.Packet; +import net.minecraft.src.Packet250CustomPayload; +import net.minecraft.src.TileEntity; +import net.minecraft.src.World; +import universalelectricity.core.Vector3; + +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteStreams; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.network.IPacketHandler; +import cpw.mods.fml.common.network.PacketDispatcher; +import cpw.mods.fml.common.network.Player; + +/** + * This class is used for sending and receiving packets between the server and + * the client. You can directly use this by registering this packet manager with + * NetworkMod. Example: + * + * @NetworkMod(channels = { "BasicComponents" }, clientSideRequired = true, + * serverSideRequired = false, packetHandler = + * PacketManager.class) + * + * Check out {@link #BasicComponents} for better reference. + * + * @author Calclavia + */ +public class PacketManager implements IPacketHandler, IPacketReceiver +{ + public enum PacketType + { + UNSPECIFIED, TILEENTITY; + + public static PacketType get(int id) + { + if (id >= 0 && id < PacketType.values().length) { return PacketType.values()[id]; } + return UNSPECIFIED; + } + } + + public static Packet getPacketWithID(String channelName, int id, Object... sendData) + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream(bytes); + + try + { + data.writeInt(id); + + data = encodeDataStream(data, sendData); + + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = channelName; + packet.data = bytes.toByteArray(); + packet.length = packet.data.length; + + return packet; + } + catch (IOException e) + { + System.out.println("Failed to create packet."); + e.printStackTrace(); + } + + return null; + } + + public static Packet getPacket(String channelName, Object... sendData) + { + return getPacketWithID(channelName, PacketType.UNSPECIFIED.ordinal(), sendData); + } + + /** + * Gets a packet for the tile entity. + * + * @return + */ + public static Packet getPacket(String channelName, TileEntity sender, Object... sendData) + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream(bytes); + + try + { + data.writeInt(PacketType.TILEENTITY.ordinal()); + + data.writeInt(sender.xCoord); + data.writeInt(sender.yCoord); + data.writeInt(sender.zCoord); + data = encodeDataStream(data, sendData); + + Packet250CustomPayload packet = new Packet250CustomPayload(); + packet.channel = channelName; + packet.data = bytes.toByteArray(); + packet.length = packet.data.length; + + return packet; + } + catch (IOException e) + { + System.out.println("Failed to create packet."); + e.printStackTrace(); + } + + return null; + } + + /** + * Sends packets to clients around a specific coordinate. A wrapper using + * Vector3. See {@PacketDispatcher} for detailed + * information. + */ + public static void sendPacketToClients(Packet packet, World worldObj, Vector3 position, double range) + { + try + { + PacketDispatcher.sendPacketToAllAround(position.x, position.y, position.z, range, worldObj.provider.dimensionId, packet); + } + catch (Exception e) + { + System.out.println("Sending packet to client failed."); + e.printStackTrace(); + } + } + + /** + * Sends a packet to all the clients on this server. + */ + public static void sendPacketToClients(Packet packet, World worldObj) + { + try + { + PacketDispatcher.sendPacketToAllInDimension(packet, worldObj.provider.dimensionId); + } + catch (Exception e) + { + System.out.println("Sending packet to client failed."); + e.printStackTrace(); + } + } + + public static void sendPacketToClients(Packet packet) + { + try + { + if (FMLCommonHandler.instance().getMinecraftServerInstance() != null) + { + FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().sendPacketToAllPlayers(packet); + } + } + catch (Exception e) + { + System.out.println("Sending packet to client failed."); + e.printStackTrace(); + } + } + + public static DataOutputStream encodeDataStream(DataOutputStream data, Object... sendData) + { + try + { + for (Object dataValue : sendData) + { + if (dataValue instanceof Integer) + { + data.writeInt((Integer) dataValue); + } + else if (dataValue instanceof Float) + { + data.writeFloat((Float) dataValue); + } + else if (dataValue instanceof Double) + { + data.writeDouble((Double) dataValue); + } + else if (dataValue instanceof Byte) + { + data.writeByte((Byte) dataValue); + } + else if (dataValue instanceof Boolean) + { + data.writeBoolean((Boolean) dataValue); + } + else if (dataValue instanceof String) + { + data.writeUTF((String) dataValue); + } + else if (dataValue instanceof Short) + { + data.writeShort((Short) dataValue); + } + else if (dataValue instanceof Long) + { + data.writeLong((Long) dataValue); + } + } + + return data; + + } + catch (IOException e) + { + System.out.println("Packet data encoding failed."); + e.printStackTrace(); + } + + return data; + } + + @Override + public void onPacketData(INetworkManager network, Packet250CustomPayload packet, Player player) + { + try + { + ByteArrayDataInput data = ByteStreams.newDataInput(packet.data); + + int packetTypeID = data.readInt(); + + PacketType packetType = PacketType.get(packetTypeID); + + if (packetType == PacketType.TILEENTITY) + { + int x = data.readInt(); + int y = data.readInt(); + int z = data.readInt(); + + World world = ((EntityPlayer) player).worldObj; + + if (world != null) + { + TileEntity tileEntity = world.getBlockTileEntity(x, y, z); + + if (tileEntity != null) + { + if (tileEntity instanceof IPacketReceiver) + { + ((IPacketReceiver) tileEntity).handlePacketData(network, packetTypeID, packet, ((EntityPlayer) player), data); + } + } + } + } + else + { + this.handlePacketData(network, packetTypeID, packet, ((EntityPlayer) player), data); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + @Override + public void handlePacketData(INetworkManager network, int packetType, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream) + { + + } +}