Posted August 22, 201411 yr I'm currently working on a power system for a friend's mod, however I'm hitting a bit of a snag. So far the cables only seem to be connecting successfully in the vertical (y) direction and transferring MF power packets accordingly. Visually, connections will only show up once the chunk has been reloaded so I'm guessing I'm failing with the update packet somewhere. Does anyone have any idea what I'm doing wrong here? package net.RPower.RPowermod.machines.power.cable; import RPower.api.power.E_MFPacketType; import RPower.api.power.MFPacket; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.RPower.RPowermod.machines.power.MFHelper; import net.minecraft.block.Block; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; public class BlockFluxCableBasic extends BlockContainer{ public BlockFluxCableBasic(Material p_i45394_1_) { super(p_i45394_1_); } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int metaD, float hitX, float hitY, float hitZ) { MFPacket temp = new MFPacket(E_MFPacketType.REQUEST); ((TileEntityFluxCable)world.getTileEntity(x, y, z)).takePacket(temp); return false; } @Override public void onNeighborBlockChange(World world, int x,int y, int z, Block block) { if((world.getBlock(x, y, z).hasTileEntity(0) && MFHelper.checkConnectable(world.getTileEntity(x, y, z)))) { ((TileEntityFluxCable)world.getTileEntity(x, y, z)).checkConnections(); } } @Override public int onBlockPlaced(World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ, int metaD) { if((world.getBlock(x, y, z).hasTileEntity(0) && MFHelper.checkConnectable(world.getTileEntity(x, y, z)))) ((TileEntityFluxCable)world.getTileEntity(x, y, z)).connections[(5-side)]=true; System.out.println("set block at ["+x+","+y+","+z+"] to: "+side); return super.onBlockPlaced(world, x, y, z,side, hitX, hitY, hitZ, metaD); } @Override public TileEntity createNewTileEntity(World world, int metadata) { TileEntity cable = new TileEntityFluxCable(32); return cable; } @Override public boolean isAir(IBlockAccess world, int x, int y, int z) { return false; } @Override protected boolean canSilkHarvest() { return false; }; @Override public boolean canSilkHarvest(World world, EntityPlayer player, int x, int y, int z, int metadata) { return false; }; @Override public boolean canBeReplacedByLeaves(IBlockAccess world, int x, int y, int z) { return false; } @SideOnly(Side.CLIENT) @Override public boolean renderAsNormalBlock() { return false; } @Override @SideOnly(Side.CLIENT) public boolean shouldSideBeRendered(IBlockAccess blockAccess, int x, int y, int z, int side) { return false; }; @SideOnly(Side.CLIENT) @Override public boolean isOpaqueCube() { return false; } @Override public int getRenderType() { return -1; } } this is the basic block class, the right-click spawned packet is purely for testing connections. package net.RPower.RPowermod.machines.power.cable; import java.util.LinkedList; import java.util.Queue; import RPower.api.power.E_MFPacketType; import RPower.api.power.I_MFSink; import RPower.api.power.MFPacket; import RPower.api.power.cable.I_MFCable; import net.RPower.RPowermod.machines.power.MFHelper; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.network.play.server.S35PacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; public class TileEntityFluxCable extends TileEntity implements I_MFCable { //Connections are an array of [up, Down, North, East, West, South] public boolean[] connections = {false, false, false, false, false, false}; //whether or not the cable is lossy public boolean insulatedCable; //maximum limit the cable can carry public double packetSizeLimit; //Packets awaiting processing public Queue<MFPacket> internalBuffer; //automatically calculated. public double percentageLoss; //transfer mode, unbridged connections can only cross an intersection in straight lines (may be reserved for advanced cabling) public boolean bridgeConnections; public TileEntityFluxCable() { this(32); } public TileEntityFluxCable(double packetSize) { this(packetSize,false); } public TileEntityFluxCable(double packetSize, boolean insulated) { this(packetSize,insulated,true); } public TileEntityFluxCable(double packetSize, boolean insulated,boolean bridged) { packetSizeLimit= packetSize; insulatedCable=insulated; bridgeConnections=bridged; internalBuffer=new LinkedList<MFPacket>(); checkLoss(insulated); } private void checkLoss(boolean insulated) { if(!insulated) { percentageLoss=(packetSizeLimit/MFPacket.POWERLIMIT); } } @Override public boolean takePacket(MFPacket packet) { double excess=0; if(!insulatedCable) { excess+=(percentageLoss*packet.getBuffer()); packet.setBuffer(packet.getBuffer()-excess); } if(packet.getBuffer()>packetSizeLimit) { excess += packet.getBuffer()-packetSizeLimit; packet.setBuffer(packetSizeLimit); } powerBleed(excess); boolean result=false; result=internalBuffer.add(packet); return result; } @Override public void writeToNBT(NBTTagCompound nbtTag) { int[] connectionsInt = new int[6]; int i = 0; for (boolean side : connections) { connectionsInt[i]=connections[i]?1:0; i++; } nbtTag.setIntArray("connections", connectionsInt); nbtTag.setBoolean("insulated", insulatedCable); nbtTag.setBoolean("bridged", bridgeConnections); nbtTag.setDouble("packetLimit", packetSizeLimit); super.writeToNBT(nbtTag); }; @Override public void readFromNBT(NBTTagCompound nbtTag) { int[] connectionsInt = nbtTag.getIntArray("connections"); int i = 0; for (boolean side : connections) { connections[i]=(connectionsInt[i]==1); i++; } insulatedCable=nbtTag.getBoolean("insulated"); bridgeConnections=nbtTag.getBoolean("bridged"); packetSizeLimit=nbtTag.getDouble("packetLimit"); checkLoss(insulatedCable); super.readFromNBT(nbtTag); }; @Override public Packet getDescriptionPacket() { NBTTagCompound nbtTag = new NBTTagCompound(); this.writeToNBT(nbtTag); //TODO: Get this damn working! return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, 1, nbtTag); } @Override public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) { readFromNBT(packet.func_148857_g()); } @Override public void updateEntity() { if(!internalBuffer.isEmpty()) { MFPacket packet = internalBuffer.remove(); boolean result=false; byte direction; for(int i=0; i<59;i++) { int posNeg = ((int)(Math.random()*%2==0)?1:-1; double randXvel=Math.random()*(2*posNeg); double randYvel=Math.random()*(2*posNeg); double randZvel=Math.random()*(2*posNeg); this.worldObj.spawnParticle("magicCrit", xCoord, yCoord, zCoord, randXvel, randYvel, randZvel); } switch(packet.getType()) { case RESPOND: direction = packet.getOrigin().peek(); result = (direction!=-1); result = pushPacket(packet); break; default: direction = packet.getOrigin().peek(); packet.getOrigin().add(randDir(direction)); result=pushPacket(packet); break; } } super.updateEntity(); } private byte randDir(byte initDirection) { byte result = -1; while((connectionNum()>=2)&&(result==-1||!connections[result])&&result!=initDirection) { result=(byte)(Math.random()*5); } return result; } public byte connectionNum() { byte result=0; for (Boolean connection : connections) { if(connection) result++; } return result; } public boolean checkConnections() { boolean result=false; int xDir=0, yDir=0, zDir=0; for(int dir=0; dir<=5; dir++) { int modifier=(dir%2==1)?1:-1; System.err.println("test vars: dir="+dir+", TestCase="+(dir/2)+", modifier="+modifier+","); switch(dir/2) { case 2: xDir=modifier; break; case 1: zDir=modifier; break; case 0: yDir=modifier; break; } System.out.println("testing ["+xDir+","+yDir+","+zDir+"]"); result = this.worldObj.getBlock(xCoord+xDir, yCoord+yDir, zCoord+zDir).hasTileEntity(0); if(result) result = MFHelper.checkConnectable(this.worldObj.getTileEntity(xCoord+xDir, yCoord+yDir, zCoord+zDir)); System.out.println("result of MF test was: "+result); int conDir = dir-modifier; System.err.println("conDir="+conDir); connections[conDir]=result; if(connections[conDir]) { System.out.println("Connection found!"); } } return result; } @Override public boolean pushPacket(MFPacket packet) { byte direction = packet.getOrigin().peek(); if(packet.getType()==E_MFPacketType.RESPOND) packet.getOrigin().pop(); boolean result= false; int xDir=0, yDir=0, zDir=0; int modifier=(direction%2==1)?-1:1; //up:1, down:0, x+:5, x-:4, z+:3,z-2; switch(direction/2) { case 2: xDir=modifier; break; case 1: zDir=modifier; break; case 0: yDir=modifier; break; } result = this.worldObj.getBlock(xCoord+xDir, yCoord+yDir, zCoord+zDir).hasTileEntity(0); if(result) result=this.worldObj.getTileEntity(xCoord+xDir, yCoord+yDir, zCoord+zDir)instanceof I_MFSink; if(result) result=((I_MFSink)this.worldObj.getTileEntity(xCoord+xDir, yCoord+yDir, zCoord+zDir)).takePacket(packet); if(!result) powerBleed(packet.getBuffer()); return result; } @Override public boolean canUpdate() { return true; } @Override public double flowLimit() { return packetSizeLimit; } @Override public void powerBleed(double excess) { //add power bleed to chunk atmosphere -> own effects + taint if Thaumcraft installed if(excess>0) System.err.println(""+excess+" MF bled off into atmosphere!\n"); } @Override public double getPacketLimit() { return packetSizeLimit; } @Override public boolean isInsulated() { return insulatedCable; } @Override public boolean isBridged() { return bridgeConnections; } @Override public boolean canDeBridge() { return insulatedCable; } @Override public boolean[] getConnections() { return connections; } } The Actual TileEntity and source of the stress here, it's meant to keep an array of connected sides and update it when neighbours change. package net.RPower.RPowermod.machines.power; import RPower.api.power.I_MFSink; import RPower.api.power.I_MFSource; import RPower.api.power.cable.I_MFCable; import net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable; import net.minecraft.tileentity.TileEntity; public class MFHelper { public static boolean checkConnectable(TileEntity tileEntity) { boolean result = (tileEntity instanceof I_MFSink || tileEntity instanceof I_MFSource); if (result) System.out.println("Success!"); System.out.println(tileEntity.toString()); return result; } } Anything I need to handle frequently will be offloaded into this class for neatness. Currently it only checks if a tileEntity implements either of the interfaces for MFcables to connect to. (I_MFCable extends both I_MFSink and I_MFSource) Cheers in advance and sorry about the code flood, the full source is on this branch: https://github.com/BackSpace47/main/tree/PowerSystem https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 25, 201411 yr Author Sorry to bump this, but I'm still struggling to make this work. Currently it's connecting and transferrign packets perfectly in the -y direction, but none other. I've tried altering the direction code to no avail and the visual connection updates still only load after a chunk reload. I've tried both notifyBlockUpdate(x,y,z,block) and scheduleBlockUpdate(x,y,z,block,metaD), both to no avail. If anyone has any insights into this, I'd be extrememy grateful! https://lh4.googleusercontent.com/-y0Z8JIlKxcY/U_rvgRmsm6I/AAAAAAAAB9M/A2kcrAVrn5w/w854-h480-no/2014-08-25_10.02.48.png[/img] Updated Code: package net.RPower.RPowermod.machines.power.cable; import java.util.LinkedList; import java.util.Queue; import RPower.api.power.E_MFPacketType; import RPower.api.power.I_MFSink; import RPower.api.power.MFPacket; import RPower.api.power.cable.I_MFCable; import net.RPower.RPowermod.core.RPCore; import net.RPower.RPowermod.machines.power.MFHelper; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.network.play.server.S35PacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; public class TileEntityFluxCable extends TileEntity implements I_MFCable { //Connections are an array of [up, Down, North, East, West, South] public boolean[] connections = {false, false, false, false, false, false}; //whether or not the cable is lossy public boolean insulatedCable; //maximum limit the cable can carry public double packetSizeLimit; //Packets awaiting processing public Queue<MFPacket> internalBuffer; //automatically calculated. public double percentageLoss; //transfer mode, unbridged connections can only cross an intersection in straight lines (may be reserved for advanced cabling) public boolean bridgeConnections; public TileEntityFluxCable() { this(32); } public TileEntityFluxCable(double packetSize) { this(packetSize,false); } public TileEntityFluxCable(double packetSize, boolean insulated) { this(packetSize,insulated,true); } public TileEntityFluxCable(double packetSize, boolean insulated,boolean bridged) { packetSizeLimit= packetSize; insulatedCable=insulated; bridgeConnections=bridged; internalBuffer=new LinkedList<MFPacket>(); checkLoss(insulated); } private void checkLoss(boolean insulated) { if(!insulated) { percentageLoss=(packetSizeLimit/MFPacket.POWERLIMIT); } } @Override public boolean takePacket(MFPacket packet) { double excess=0; if(!insulatedCable) { excess+=(percentageLoss*packet.getBuffer()); packet.setBuffer(packet.getBuffer()-excess); } if(packet.getBuffer()>packetSizeLimit) { excess += packet.getBuffer()-packetSizeLimit; packet.setBuffer(packetSizeLimit); } powerBleed(excess); boolean result=false; result=internalBuffer.add(packet); return result; } @Override public void writeToNBT(NBTTagCompound nbtTag) { int[] connectionsInt = new int[6]; int i = 0; for (boolean side : connections) { connectionsInt[i]=connections[i]?1:0; i++; } nbtTag.setIntArray("connections", connectionsInt); nbtTag.setBoolean("insulated", insulatedCable); nbtTag.setBoolean("bridged", bridgeConnections); nbtTag.setDouble("packetLimit", packetSizeLimit); super.writeToNBT(nbtTag); }; @Override public void readFromNBT(NBTTagCompound nbtTag) { int[] connectionsInt = nbtTag.getIntArray("connections"); int i = 0; for (boolean side : connections) { connections[i]=(connectionsInt[i]==1); i++; } insulatedCable=nbtTag.getBoolean("insulated"); bridgeConnections=nbtTag.getBoolean("bridged"); packetSizeLimit=nbtTag.getDouble("packetLimit"); checkLoss(insulatedCable); super.readFromNBT(nbtTag); }; @Override public Packet getDescriptionPacket() { NBTTagCompound nbtTag = new NBTTagCompound(); this.writeToNBT(nbtTag); //TODO: Get this damn working! return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, 1, nbtTag); } @Override public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) { readFromNBT(packet.func_148857_g()); } @Override public void updateEntity() { if(!internalBuffer.isEmpty()) { MFPacket packet = internalBuffer.remove(); boolean result=false; byte direction; for(int i=0; i<59;i++) { int posNeg = ((int)(Math.random()*%2==0)?1:-1; double randXvel=Math.random()*(2*posNeg); double randYvel=Math.random()*(2*posNeg); double randZvel=Math.random()*(2*posNeg); this.worldObj.spawnParticle("magicCrit", xCoord, yCoord, zCoord, randXvel, randYvel, randZvel); } switch(packet.getType()) { case RESPOND: direction = packet.getOrigin().peek(); result = (direction!=-1); result = pushPacket(packet); break; default: direction = packet.getOrigin().peek(); packet.getOrigin().add(randDir(direction)); result=pushPacket(packet); break; } } super.updateEntity(); } private byte randDir(byte initDirection) { byte result = -1; while((connectionNum()>=2)&&(result==-1||!connections[result])&&result!=initDirection) { result=(byte)(Math.random()*5); } return result; } public byte connectionNum() { byte result=0; for (Boolean connection : connections) { if(connection) result++; } return result; } public boolean checkConnections() { boolean result=false; int xDir=0, yDir=0, zDir=0; for(int dir=0; dir<=5; dir++) { int modifier=(dir%2==1)?1:-1; System.err.println("test vars: dir="+dir+", TestCase="+(dir/2)+", modifier="+modifier+","); switch(dir/2) { case 2: xDir=modifier; break; case 1: zDir=modifier; break; case 0: yDir=modifier; break; } System.out.println("testing ["+xDir+","+yDir+","+zDir+"]"); result = this.worldObj.getBlock(xCoord+xDir, yCoord+yDir, zCoord+zDir).hasTileEntity(0); if(result) result = MFHelper.checkConnectable(this.worldObj.getTileEntity(xCoord+xDir, yCoord+yDir, zCoord+zDir)); System.out.println("result of MF test was: "+result); int conDir = dir-modifier; System.err.println("conDir="+conDir); connections[conDir]=result; if(connections[conDir]) { System.out.println("Connection found!"); worldObj.scheduleBlockUpdate(xCoord, yCoord, zCoord, getBlockType(), worldObj.getBlockMetadata(xCoord, yCoord, zCoord)); } } return result; } @Override public boolean pushPacket(MFPacket packet) { byte direction = packet.getOrigin().peek(); if(packet.getType()==E_MFPacketType.RESPOND) packet.getOrigin().pop(); boolean result= false; int xDir=0, yDir=0, zDir=0; int modifier=(direction%2==1)?-1:1; //up:1, down:0, x+:5, x-:4, z+:3,z-2; switch(direction/2) { case 2: xDir=modifier; break; case 1: zDir=modifier; break; case 0: yDir=modifier; break; } result = this.worldObj.getBlock(xCoord+xDir, yCoord+yDir, zCoord+zDir).hasTileEntity(0); if(result) result=this.worldObj.getTileEntity(xCoord+xDir, yCoord+yDir, zCoord+zDir)instanceof I_MFSink; if(result) result=((I_MFSink)this.worldObj.getTileEntity(xCoord+xDir, yCoord+yDir, zCoord+zDir)).takePacket(packet); if(!result) powerBleed(packet.getBuffer()); return result; } @Override public boolean canUpdate() { return true; } @Override public double flowLimit() { return packetSizeLimit; } @Override public void powerBleed(double excess) { //add power bleed to chunk atmosphere -> own effects + taint if Thaumcraft installed if(excess>0) System.err.println(""+excess+" MF bled off into atmosphere!\n"); } @Override public double getPacketLimit() { return packetSizeLimit; } @Override public boolean isInsulated() { return insulatedCable; } @Override public boolean isBridged() { return bridgeConnections; } @Override public boolean canDeBridge() { return insulatedCable; } @Override public boolean[] getConnections() { return connections; } } https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 25, 201411 yr Could you show me how you render your pipes? Do you have a tile entity special renderer binded somewhere? Are the print in your check connections printing the right values? If they are not try considering make it look fancier using ForgeDirection(s can't remember if plural). Write and read nbt should be good, but check them too (they are used to sync with the client after all and you never know). While you are at it, put some print in that renderer and see if it receive the right stuff. If it does, you know where the problem lies then Check out my blog! http://www.whov.altervista.org
August 25, 201411 yr Author Just a head's up, the model is a lot of faces: // Date: 21/08/2014 21:03:22 // Template version 1.1 // Java generated by Techne // Keep in mind that you still need to fill in some blanks // - ZeuX package net.RPower.RPowermod.model.block; import net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable; import net.RPower.RPowermod.renderers.block.TileEntityFluxCableRenderer; import net.minecraft.client.model.*; import net.minecraft.entity.Entity; import net.minecraft.tileentity.TileEntity; public class ModelFluxCableBasic extends ModelBase { //fields ModelRenderer fFaceR; ModelRenderer fFaceU; ModelRenderer fFaceD; ModelRenderer fFaceL; ModelRenderer fcoreL; ModelRenderer fcoreR; ModelRenderer lFaceB; ModelRenderer lFaceU; ModelRenderer lFaceD; ModelRenderer lFaceF; ModelRenderer lcoreL; ModelRenderer lcoreR; ModelRenderer rFaceB; ModelRenderer rFaceU; ModelRenderer rFaceD; ModelRenderer rFaceF; ModelRenderer rcoreL; ModelRenderer rcoreR; ModelRenderer coreR; ModelRenderer coreF; ModelRenderer coreL; ModelRenderer coreD; ModelRenderer coreB; ModelRenderer coreU; ModelRenderer dFaceB; ModelRenderer dFaceL; ModelRenderer dFaceR; ModelRenderer dFaceF; ModelRenderer dcoreL; ModelRenderer dcoreR; ModelRenderer uFaceB; ModelRenderer uFaceL; ModelRenderer uFaceR; ModelRenderer uFaceF; ModelRenderer ucoreL; ModelRenderer ucoreR; ModelRenderer bFaceR; ModelRenderer bFaceU; ModelRenderer bFaceD; ModelRenderer bFaceL; ModelRenderer bcoreL; ModelRenderer bcoreR; public ModelFluxCableBasic() { textureWidth = 16; textureHeight = 16; fFaceR = new ModelRenderer(this, 0, 0); fFaceR.addBox(0F, 0F, 0F, 6, 3, 0); fFaceR.setRotationPoint(-2F, 16F, -8F); fFaceR.setTextureSize(16, 16); fFaceR.mirror = true; setRotation(fFaceR, -2.356194F, -1.570796F, 0F); fFaceU = new ModelRenderer(this, 0, 0); fFaceU.addBox(0F, 0F, 0F, 6, 3, 0); fFaceU.setRotationPoint(2F, 16F, -8F); fFaceU.setTextureSize(16, 16); fFaceU.mirror = true; setRotation(fFaceU, 2.356194F, -1.570796F, 0F); fFaceD = new ModelRenderer(this, 0, 0); fFaceD.addBox(0F, 0F, 0F, 6, 3, 0); fFaceD.setRotationPoint(-2F, 16F, -8F); fFaceD.setTextureSize(16, 16); fFaceD.mirror = true; setRotation(fFaceD, -0.7853982F, -1.570796F, 0F); fFaceL = new ModelRenderer(this, 0, 0); fFaceL.addBox(0F, 0F, 0F, 6, 3, 0); fFaceL.setRotationPoint(2F, 16F, -8F); fFaceL.setTextureSize(16, 16); fFaceL.mirror = true; setRotation(fFaceL, 0.7853982F, -1.570796F, 0F); fcoreL = new ModelRenderer(this, 0, 6); fcoreL.addBox(0F, 0F, 0F, 6, 2, 0); fcoreL.setRotationPoint(-1F, 16F, -2F); fcoreL.setTextureSize(16, 16); fcoreL.mirror = true; setRotation(fcoreL, 1.570796F, 1.570796F, 0F); fcoreR = new ModelRenderer(this, 0, 6); fcoreR.addBox(0F, 0F, 0F, 6, 2, 0); fcoreR.setRotationPoint(0F, 15F, -2F); fcoreR.setTextureSize(16, 16); fcoreR.mirror = true; setRotation(fcoreR, 0F, 1.570796F, 0F); lFaceB = new ModelRenderer(this, 0, 0); lFaceB.addBox(0F, 0F, 0F, 6, 3, 0); lFaceB.setRotationPoint(2F, 16F, 2F); lFaceB.setTextureSize(16, 16); lFaceB.mirror = true; setRotation(lFaceB, -2.356194F, 0F, 0F); lFaceU = new ModelRenderer(this, 0, 0); lFaceU.addBox(0F, 0F, 0F, 6, 3, 0); lFaceU.setRotationPoint(2F, 16F, -2F); lFaceU.setTextureSize(16, 16); lFaceU.mirror = true; setRotation(lFaceU, 2.356194F, 0F, 0F); lFaceD = new ModelRenderer(this, 0, 0); lFaceD.addBox(0F, 0F, 0F, 6, 3, 0); lFaceD.setRotationPoint(2F, 16F, 2F); lFaceD.setTextureSize(16, 16); lFaceD.mirror = true; setRotation(lFaceD, -0.7853982F, 0F, 0F); lFaceF = new ModelRenderer(this, 0, 0); lFaceF.addBox(0F, 0F, 0F, 6, 3, 0); lFaceF.setRotationPoint(2F, 16F, -2F); lFaceF.setTextureSize(16, 16); lFaceF.mirror = true; setRotation(lFaceF, 0.7853982F, -0.0069813F, 0F); lcoreL = new ModelRenderer(this, 0, 6); lcoreL.addBox(0F, 0F, 0F, 6, 2, 0); lcoreL.setRotationPoint(2F, 16F, -1F); lcoreL.setTextureSize(16, 16); lcoreL.mirror = true; setRotation(lcoreL, 1.570796F, 0F, 0F); lcoreR = new ModelRenderer(this, 0, 6); lcoreR.addBox(0F, 0F, 0F, 6, 2, 0); lcoreR.setRotationPoint(2F, 15F, 0F); lcoreR.setTextureSize(16, 16); lcoreR.mirror = true; setRotation(lcoreR, 0F, 0F, 0F); rFaceB = new ModelRenderer(this, 0, 0); rFaceB.addBox(0F, 0F, 0F, 6, 3, 0); rFaceB.setRotationPoint(-8F, 16F, 2F); rFaceB.setTextureSize(16, 16); rFaceB.mirror = true; setRotation(rFaceB, -0.7853982F, 0F, 0F); rFaceU = new ModelRenderer(this, 0, 0); rFaceU.addBox(0F, 0F, 0F, 6, 3, 0); rFaceU.setRotationPoint(-8F, 14F, 0F); rFaceU.setTextureSize(16, 16); rFaceU.mirror = true; setRotation(rFaceU, 0.7853982F, 0F, 0F); rFaceD = new ModelRenderer(this, 0, 0); rFaceD.addBox(0F, 0F, 0F, 6, 3, 0); rFaceD.setRotationPoint(-8F, 18F, 0F); rFaceD.setTextureSize(16, 16); rFaceD.mirror = true; setRotation(rFaceD, -2.356194F, 0F, 0F); rFaceF = new ModelRenderer(this, 0, 0); rFaceF.addBox(0F, 0F, 0F, 6, 3, 0); rFaceF.setRotationPoint(-8F, 14F, 0F); rFaceF.setTextureSize(16, 16); rFaceF.mirror = true; setRotation(rFaceF, -0.7853982F, 0F, 0F); rcoreL = new ModelRenderer(this, 0, 6); rcoreL.addBox(0F, 0F, 0F, 6, 2, 0); rcoreL.setRotationPoint(-8F, 16F, -1F); rcoreL.setTextureSize(16, 16); rcoreL.mirror = true; setRotation(rcoreL, 1.570796F, 0F, 0F); rcoreR = new ModelRenderer(this, 0, 6); rcoreR.addBox(0F, 0F, 0F, 6, 2, 0); rcoreR.setRotationPoint(-8F, 15F, 0F); rcoreR.setTextureSize(16, 16); rcoreR.mirror = true; setRotation(rcoreR, 0F, 0F, 0F); coreR = new ModelRenderer(this, 0, 12); coreR.addBox(0F, 0F, 0F, 4, 4, 0); coreR.setRotationPoint(-2F, 14F, 2F); coreR.setTextureSize(16, 16); coreR.mirror = true; setRotation(coreR, 0F, 1.570796F, 0F); coreF = new ModelRenderer(this, 0, 12); coreF.addBox(0F, 0F, 0F, 4, 4, 0); coreF.setRotationPoint(-2F, 14F, -2F); coreF.setTextureSize(16, 16); coreF.mirror = true; setRotation(coreF, 0F, 0F, 0F); coreL = new ModelRenderer(this, 0, 12); coreL.addBox(0F, 0F, 0F, 4, 4, 0); coreL.setRotationPoint(2F, 14F, -2F); coreL.setTextureSize(16, 16); coreL.mirror = true; setRotation(coreL, 0F, -1.570796F, 0F); coreD = new ModelRenderer(this, 0, 12); coreD.addBox(0F, 0F, 0F, 4, 4, 0); coreD.setRotationPoint(2F, 18F, 2F); coreD.setTextureSize(16, 16); coreD.mirror = true; setRotation(coreD, 1.570796F, -3.141593F, 0F); coreB = new ModelRenderer(this, 0, 12); coreB.addBox(0F, 0F, 0F, 4, 4, 0); coreB.setRotationPoint(2F, 14F, 2F); coreB.setTextureSize(16, 16); coreB.mirror = true; setRotation(coreB, 0F, -3.141593F, 0F); coreU = new ModelRenderer(this, 0, 12); coreU.addBox(0F, 0F, 0F, 4, 4, 0); coreU.setRotationPoint(2F, 14F, -2F); coreU.setTextureSize(16, 16); coreU.mirror = true; setRotation(coreU, -1.570796F, 3.141593F, 0F); dFaceB = new ModelRenderer(this, 0, 0); dFaceB.addBox(0F, 0F, 0F, 6, 3, 0); dFaceB.setRotationPoint(2F, 18F, 0F); dFaceB.setTextureSize(16, 16); dFaceB.mirror = true; setRotation(dFaceB, 0.7853982F, 0F, 1.570796F); dFaceL = new ModelRenderer(this, 0, 0); dFaceL.addBox(0F, 0F, 0F, 6, 3, 0); dFaceL.setRotationPoint(0F, 18F, -2F); dFaceL.setTextureSize(16, 16); dFaceL.mirror = true; setRotation(dFaceL, 2.356194F, 0F, 1.570796F); dFaceR = new ModelRenderer(this, 0, 0); dFaceR.addBox(0F, 0F, 0F, 6, 3, 0); dFaceR.setRotationPoint(-2F, 18F, 0F); dFaceR.setTextureSize(16, 16); dFaceR.mirror = true; setRotation(dFaceR, 2.356194F, 0F, 1.570796F); dFaceF = new ModelRenderer(this, 0, 0); dFaceF.addBox(0F, 0F, 0F, 6, 3, 0); dFaceF.setRotationPoint(0F, 18F, -2F); dFaceF.setTextureSize(16, 16); dFaceF.mirror = true; setRotation(dFaceF, 0.7853982F, 0F, 1.570796F); dcoreL = new ModelRenderer(this, 0, 6); dcoreL.addBox(0F, 0F, 0F, 6, 2, 0); dcoreL.setRotationPoint(0F, 18F, -1F); dcoreL.setTextureSize(16, 16); dcoreL.mirror = true; setRotation(dcoreL, 1.570796F, 0F, 1.570796F); dcoreR = new ModelRenderer(this, 0, 6); dcoreR.addBox(0F, 0F, 0F, 6, 2, 0); dcoreR.setRotationPoint(1F, 18F, 0F); dcoreR.setTextureSize(16, 16); dcoreR.mirror = true; setRotation(dcoreR, 0F, 0F, 1.570796F); uFaceB = new ModelRenderer(this, 0, 0); uFaceB.addBox(0F, 0F, 0F, 6, 3, 0); uFaceB.setRotationPoint(2F, 8F, 0F); uFaceB.setTextureSize(16, 16); uFaceB.mirror = true; setRotation(uFaceB, 0.7853982F, 0F, 1.570796F); uFaceL = new ModelRenderer(this, 0, 0); uFaceL.addBox(0F, 0F, 0F, 6, 3, 0); uFaceL.setRotationPoint(0F, 8F, -2F); uFaceL.setTextureSize(16, 16); uFaceL.mirror = true; setRotation(uFaceL, 2.356194F, 0F, 1.570796F); uFaceR = new ModelRenderer(this, 0, 0); uFaceR.addBox(0F, 0F, 0F, 6, 3, 0); uFaceR.setRotationPoint(-2F, 8F, 0F); uFaceR.setTextureSize(16, 16); uFaceR.mirror = true; setRotation(uFaceR, 2.356194F, 0F, 1.570796F); uFaceF = new ModelRenderer(this, 0, 0); uFaceF.addBox(0F, 0F, 0F, 6, 3, 0); uFaceF.setRotationPoint(0F, 8F, -2F); uFaceF.setTextureSize(16, 16); uFaceF.mirror = true; setRotation(uFaceF, 0.7853982F, 0F, 1.570796F); ucoreL = new ModelRenderer(this, 0, 6); ucoreL.addBox(0F, 0F, 0F, 6, 2, 0); ucoreL.setRotationPoint(0F, 8F, -1F); ucoreL.setTextureSize(16, 16); ucoreL.mirror = true; setRotation(ucoreL, 1.570796F, 0F, 1.570796F); ucoreR = new ModelRenderer(this, 0, 6); ucoreR.addBox(0F, 0F, 0F, 6, 2, 0); ucoreR.setRotationPoint(1F, 8F, 0F); ucoreR.setTextureSize(16, 16); ucoreR.mirror = true; setRotation(ucoreR, 0F, 0F, 1.570796F); bFaceR = new ModelRenderer(this, 0, 0); bFaceR.addBox(0F, 0F, 0F, 6, 3, 0); bFaceR.setRotationPoint(-2F, 16F, 2F); bFaceR.setTextureSize(16, 16); bFaceR.mirror = true; setRotation(bFaceR, -2.356194F, -1.570796F, 0F); bFaceU = new ModelRenderer(this, 0, 0); bFaceU.addBox(0F, 0F, 0F, 6, 3, 0); bFaceU.setRotationPoint(2F, 16F, 2F); bFaceU.setTextureSize(16, 16); bFaceU.mirror = true; setRotation(bFaceU, 2.356194F, -1.570796F, 0F); bFaceD = new ModelRenderer(this, 0, 0); bFaceD.addBox(0F, 0F, 0F, 6, 3, 0); bFaceD.setRotationPoint(-2F, 16F, 2F); bFaceD.setTextureSize(16, 16); bFaceD.mirror = true; setRotation(bFaceD, -0.7853982F, -1.570796F, 0F); bFaceL = new ModelRenderer(this, 0, 0); bFaceL.addBox(0F, 0F, 0F, 6, 3, 0); bFaceL.setRotationPoint(2F, 16F, 2F); bFaceL.setTextureSize(16, 16); bFaceL.mirror = true; setRotation(bFaceL, 0.7853982F, -1.570796F, 0F); bcoreL = new ModelRenderer(this, 0, 6); bcoreL.addBox(0F, 0F, 0F, 6, 2, 0); bcoreL.setRotationPoint(-1F, 16F, 8F); bcoreL.setTextureSize(16, 16); bcoreL.mirror = true; setRotation(bcoreL, 1.570796F, 1.570796F, 0F); bcoreR = new ModelRenderer(this, 0, 6); bcoreR.addBox(0F, 0F, 0F, 6, 2, 0); bcoreR.setRotationPoint(0F, 15F, 8F); bcoreR.setTextureSize(16, 16); bcoreR.mirror = true; setRotation(bcoreR, 0F, 1.570796F, 0F); } public void render(TileEntity entity, float f, float f1, float f2, float f3, float f4, float f5) { boolean[] connections = {false, false, false, false, false, false}; if (entity instanceof TileEntityFluxCable) connections= ((TileEntityFluxCable)entity).connections; super.render((Entity)null, f, f1, f2, f3, f4, f5); setRotationAngles(f, f1, f2, f3, f4, f5, (Entity)null); if (connections[3]){ fFaceR.render(f5); fFaceU.render(f5); fFaceD.render(f5); fFaceL.render(f5); fcoreL.render(f5); fcoreR.render(f5); } if (connections[5]){ lFaceB.render(f5); lFaceU.render(f5); lFaceD.render(f5); lFaceF.render(f5); lcoreL.render(f5); lcoreR.render(f5); } if (connections[4]){ rFaceB.render(f5); rFaceU.render(f5); rFaceD.render(f5); rFaceF.render(f5); rcoreL.render(f5); rcoreR.render(f5); } coreR.render(f5); coreF.render(f5); coreL.render(f5); coreD.render(f5); coreB.render(f5); coreU.render(f5); if (connections[1]){ dFaceB.render(f5); dFaceL.render(f5); dFaceR.render(f5); dFaceF.render(f5); dcoreL.render(f5); dcoreR.render(f5); } if (connections[0]){ uFaceB.render(f5); uFaceL.render(f5); uFaceR.render(f5); uFaceF.render(f5); ucoreL.render(f5); ucoreR.render(f5); } if (connections[2]){ bFaceR.render(f5); bFaceU.render(f5); bFaceD.render(f5); bFaceL.render(f5); bcoreL.render(f5); bcoreR.render(f5); } } private void setRotation(ModelRenderer model, float x, float y, float z) { model.rotateAngleX = x; model.rotateAngleY = y; model.rotateAngleZ = z; } public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity entity){ super.setRotationAngles(f, f1, f2, f3, f4, f5, entity); } } As for binding, yes it's registered in the clientProxy in the function: @Override public void registerRenderers(){ ClientRegistry.bindTileEntitySpecialRenderer(TileEntityFluxCable.class, new TileEntityFluxCableRenderer()); } From the console output, it finds the cables on the right sides and returns "true", if I set the connections array manually, either in the code or with the onBlockActivated, I get get it to correctly display or connect to any dirction I wish without issue, it really is just the automatic connection mode. I hadn't heard of ForgeDirections though, I'll take a look at that, thanks! I was using the side-to-direction mapping that Grey's site gives, calculating the details from the (0 to 5)%2 for positive/negative switching and (0 to 5)/2 for the three axis. https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 25, 201411 yr In my opinion I think you would be better off hardcoding it in GL, because this way you don't have to create a new model in Techne for every option. You can simply use GL.rotatef(params here) and only have to create the basic pipe and the pipe connection. Also, ForgeDirection is an Enum which pairs a number to every compass point you can be looking at and UP and DOWN. So, for instance, 0 is South, and 1 is North, and things like that. You can use these to determine on which compass point/UP or DOWN the pipe is at and create a visual connection. As to your mechanical problem, I'm not entirely sure of the solution, as I have never really done something like it, but I'm sure someone else will present the solution. I am the self-nominated Lord of the Mastodons and don't you dare deny it. Also, check out my YouTube channel: https://www.youtube.com/user/DerpDerp44/
August 25, 201411 yr Yea, I would really recommend using OpenGL (here's a tut by a great teacher: ). Moreover, if I recall correctly, Forge directions has arrays for every direction like {+1;0;0} for north or something, so you don't have to use that huge (compared to how long it could become) code to get the direction you want. Besides, it looks to me like your problem is indeed in check connections, so we'll need to improve it. I might write something for you later today (for reference: 12 am now) Check out my blog! http://www.whov.altervista.org
August 25, 201411 yr Author I think I'll have to swap over to the directions Enum actually, it sounds much neater and somewhat less frustrating. as for the openGL, I've been sorely tempted to, this started out as a proof of cencept, to let me see the connections that the pipes were making on the code level. also, another little update, by adding the following to the Block class, I'm getting some rather interesting results.. @Override public void onNeighborChange(IBlockAccess world, int x, int y, int z,int tileX, int tileY, int tileZ) { if(world.getBlock(tileX, tileY, tileZ).hasTileEntity(0) &&MFHelper.checkConnectable(world.getTileEntity(tileX, tileY, tileZ))) { int diffX=x-tileX; int diffY=y-tileY; int diffZ=z-tileZ; int side = 0; if (diffX!=0) side=4; if (diffZ!=0) side=2; if (diffY!=0) side=0; int sideDir=(diffX<0||diffY<0|diffZ<0)?0:1; side+=sideDir; ((TileEntityFluxCable)world.getTileEntity(x, y, z)).connections[side]=true; ((TileEntityFluxCable)world.getTileEntity(tileX, tileY, tileZ)).connections[side-=sideDir]=true; } super.onNeighborChange(world, x, y, z, tileX, tileY, tileZ); } https://lh6.googleusercontent.com/-N4-qAOds6d4/U_sGZXq5OJI/AAAAAAAAB9w/vRdSYcWbflI/w854-h480-no/2014-08-25_11.43.51.png[/img] Also, cheers Whov and Mastodon, I'll slice and dice checkConnections() myself too (11:50 am here, so plenty of the time left in the day for me) https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 25, 201411 yr Also, I think that something you should try to do is integrate the visual code and the mechanical code, so that automatically when it creates a visual connection it creates a mechanical connection. This is what many big name mod authors do, and it seems to work great, so maybe try it out instead of hardcoding every single possibility of connection, try that. Some pseudo code: Your render class: public void visualConnection() { //Your connection code here } public void onVisualConnection() { if(visualConnection == true) { mechanicalConnection(); } } public void mechanicalConnection() { //Your mechanical connection code here } This way, whenever you make a visual connection, a mechanical connection automatically gets created. I probably did not make that realistic, but then again it's pseudo code from a dev. I am the self-nominated Lord of the Mastodons and don't you dare deny it. Also, check out my YouTube channel: https://www.youtube.com/user/DerpDerp44/
August 25, 201411 yr Author I'll admit that I'm loathe to do that, while it could have offload some processing to clients, it also relies on the renderer being called for the connections to be functional. I'm going to look into the tesselator now and scrap most of my old code by the way. It also adds in some interesting possibilities for efficiency. https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 25, 201411 yr public class test extends TileEntity { public boolean[] connections = new int[]{0,0,0,0,0,0}; public void checkConnections() { ForgeDirection dir; TileEntity tile; for (int i=0;i<6;i++) { dir = ForgeDirection.getOrientation(i); tile = this.worldObj.getTileEntity(this.xCoord+dir.offsetX, this.yCoord+dir.offsetY, this.zCoord+dir.offsetZ); if (tile==null) { connections = 0; } else if (tile instanceof test) { connections = 1; ((test)tile).connections[ForgeDirection.OPPOSITES] = 1; } } } } Might work? Check out my blog! http://www.whov.altervista.org
August 25, 201411 yr I'll admit that I'm loathe to do that, while it could have offload some processing to clients, it also relies on the renderer being called for the connections to be functional. I'm going to look into the tesselator now and scrap most of my old code by the way. It also adds in some interesting possibilities for efficiency. Didn't really think of that, thanks for bringing that up. In that case, it is probably not a good idea to do it specifically the way I pseudo coded it, maybe have the renderer rely on the mechanical connection, but it probably would be a good idea to find some way to get the code to realize that in the event of either connection not happening, make it happen so that things work. I am the self-nominated Lord of the Mastodons and don't you dare deny it. Also, check out my YouTube channel: https://www.youtube.com/user/DerpDerp44/
August 25, 201411 yr Author Thanks for the suggestion Whov, but since moving over to using direction Enums, I've kind of gutted the old code for now, this recode should also support "compound directions" too, or in other words, Diagonally connecting pipes. Cheers again for the suggestion of using Tessellator instead, it's proving a little hit&miss to rebuild the model but definitely worth it. I'll repost here with news of either success or failure with this recode. https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 26, 201411 yr Author Warning: Code Flood Incoming Below I've torn apart the code and rewritten a lot of it, by and large, it's cleaner and stabler, but I am getting a really strange bug now. If I check the number of connections on a pipe block, it seems to spawn with 6 connections in it's list even with no blocks around it and this is hampering my efforts to test individual pipe rendering directions working together. Just to clarify, the rendering I can now handle fine, it's the weird connection list behaviour that's confusing me now. [spoiler= Interfaces] package RPower.api.power.cable; import java.util.List; import RPower.api.power.I_MFSink; import RPower.api.power.I_MFSource; public interface I_MFCable extends I_MFSink, I_MFSource{ public double getPacketLimit(); public boolean isInsulated(); public boolean isBridged(); public boolean canDeBridge(); public List<I_PipeDirection> getConnections(); public void formConnection(boolean twoWay, int x, int y, int z); public void breakConnection(I_PipeDirection direction); } package RPower.api.power.cable; public interface I_PipeDirection { public void setTarget(int[] target); public int[] getTarget(); public byte toByte(); } [spoiler=Abstract Classes] package RPower.api.power.cable; public class A_PipeDirection implements I_PipeDirection { protected int[] target = {0,0,0}; public A_PipeDirection(int xOffset, int yOffset, int zOffset) { int[] targetArr= {xOffset,yOffset,zOffset}; setTarget(targetArr); } public A_PipeDirection(byte b) { //y = b/100 (nearest whole) int yOffset = (byte)b/100; //remove the processed value from the byte b-=(100*yOffset); //x = (b/10)-1 (again, nearest whole and convert 0-> -1, 1 -> 0, 2 -> 1) int xOffset = (b/10)-1; //remove the processed value from the byte b-= (10*(xOffset+1)); //z = b-1 (converting 0-> -1, 1 -> 0, 2 -> 1) int zOffset = b-1; int[] targetArr= {xOffset,yOffset,zOffset}; setTarget(targetArr); } @Override public void setTarget(int[] target) { this.target = target; } @Override public int[] getTarget() { return target; } @Override public byte toByte() { //=(100*y)+(10*(x+1))+(z+1) //used for saving in NBT byte result = (byte) ((100*target[1]) + (10*(1+target[0])) + (1+target[2])); return result; } } [spoiler=normal API classes] package RPower.api.power; import java.util.Stack; public class MFPacket { public static final double POWERLIMIT = 2048; private E_MFPacketType packetType; private Stack<Byte> packetOrigin; private double buffer; public MFPacket(E_MFPacketType type) { setType(type); setBuffer(0); packetOrigin = new Stack(); packetOrigin.add((byte)-1); } public E_MFPacketType getType() { return packetType; } public void setType(E_MFPacketType type) { packetType=type; } public double getBuffer() { return buffer; } public void setBuffer(double amount) { if(amount<0) amount=0; buffer=amount; } public Stack<Byte> getOrigin() { return packetOrigin; } } package RPower.api.power; import RPower.api.power.cable.I_MFCable; import RPower.api.power.cable.I_PipeDirection; import net.RPower.RPowermod.machines.power.cable.PipeDirection; import net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable; import net.minecraft.tileentity.TileEntity; public class MFHelper { public static synchronized boolean checkConnectable(TileEntity tileEntity) { boolean result = (tileEntity instanceof I_MFSink || tileEntity instanceof I_MFSource); if (result) System.out.println("Success!"); System.out.println(tileEntity.toString()); return result; } } [spoiler=Block & TileEntity] package net.RPower.RPowermod.machines.power.cable; import RPower.api.power.E_MFPacketType; import RPower.api.power.MFHelper; import RPower.api.power.MFPacket; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.block.Block; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; public class BlockFluxCable extends BlockContainer{ public BlockFluxCable(Material p_i45394_1_) { super(p_i45394_1_); } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int metaD, float hitX, float hitY, float hitZ) { // MFPacket temp = new MFPacket(E_MFPacketType.REQUEST); // ((TileEntityFluxCable)world.getTileEntity(x, y, z)).takePacket(temp); System.err.println("This pipe has "+((TileEntityFluxCable)world.getTileEntity(x, y, z)).getConnections().size()+" connections."); return false; } @Override public void onBlockAdded(World world, int x, int y, int z) { ((TileEntityFluxCable)world.getTileEntity(x, y, z)).checkConnections(); super.onBlockAdded(world, x, y, z); } @Override public TileEntity createNewTileEntity(World world, int metadata) { TileEntity cable = new TileEntityFluxCable(32); return cable; } @Override public boolean isAir(IBlockAccess world, int x, int y, int z) { return false; } @Override protected boolean canSilkHarvest() { return false; }; @Override public boolean canSilkHarvest(World world, EntityPlayer player, int x, int y, int z, int metadata) { return false; }; @Override public boolean canBeReplacedByLeaves(IBlockAccess world, int x, int y, int z) { return false; } @SideOnly(Side.CLIENT) @Override public boolean renderAsNormalBlock() { return false; } @Override @SideOnly(Side.CLIENT) public boolean shouldSideBeRendered(IBlockAccess blockAccess, int x, int y, int z, int side) { return false; }; @SideOnly(Side.CLIENT) @Override public boolean isOpaqueCube() { return false; } @Override public int getRenderType() { return -1; } } package net.RPower.RPowermod.machines.power.cable; import java.util.LinkedList; import java.util.List; import java.util.Queue; import RPower.api.power.E_MFPacketType; import RPower.api.power.I_MFSink; import RPower.api.power.MFHelper; import RPower.api.power.MFPacket; import RPower.api.power.cable.I_MFCable; import RPower.api.power.cable.I_PipeDirection; import net.RPower.RPowermod.core.RPCore; import net.minecraft.block.Block; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.network.play.server.S35PacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.ForgeDirection; public class TileEntityFluxCable extends TileEntity implements I_MFCable { //Connections are an array of [up, Down, North, East, West, South] public List<I_PipeDirection> connections; //whether or not the cable is lossy public boolean insulatedCable; //maximum limit the cable can carry public double packetSizeLimit; //Packets awaiting processing public Queue<MFPacket> internalBuffer; //automatically calculated. public double percentageLoss; //transfer mode, unbridged connections can only cross an intersection in straight lines (may be reserved for advanced cabling) public boolean bridgeConnections; public TileEntityFluxCable() { this(32); } public TileEntityFluxCable(double packetSize) { this(packetSize,false); } public TileEntityFluxCable(double packetSize, boolean insulated) { this(packetSize,insulated,true); } public TileEntityFluxCable(double packetSize, boolean insulated,boolean bridged) { packetSizeLimit= packetSize; insulatedCable=insulated; bridgeConnections=bridged; connections=new LinkedList<I_PipeDirection>(); internalBuffer=new LinkedList<MFPacket>(); checkLoss(insulated); } private void checkLoss(boolean insulated) { if(!insulated) { percentageLoss=(packetSizeLimit/MFPacket.POWERLIMIT); } } @Override public boolean takePacket(MFPacket packet) { double excess=0; if(!insulatedCable) { excess+=(percentageLoss*packet.getBuffer()); packet.setBuffer(packet.getBuffer()-excess); } if(packet.getBuffer()>packetSizeLimit) { excess += packet.getBuffer()-packetSizeLimit; packet.setBuffer(packetSizeLimit); } powerBleed(excess); boolean result=false; result=internalBuffer.add(packet); return result; } @Override public void writeToNBT(NBTTagCompound nbtTag) { byte[] connectionsArr = new byte[connections.size()]; int i =0; for (I_PipeDirection connection: connections) { connectionsArr[i] = connection.toByte(); i++; } nbtTag.setByteArray("connections", connectionsArr); nbtTag.setBoolean("insulated", insulatedCable); nbtTag.setBoolean("bridged", bridgeConnections); nbtTag.setDouble("packetLimit", packetSizeLimit); super.writeToNBT(nbtTag); }; @Override public void readFromNBT(NBTTagCompound nbtTag) { byte[] connectionsArr = nbtTag.getByteArray("connections"); for (byte b : connectionsArr) { I_PipeDirection temp = new PipeDirection(b); connections.add(temp); } insulatedCable=nbtTag.getBoolean("insulated"); bridgeConnections=nbtTag.getBoolean("bridged"); packetSizeLimit=nbtTag.getDouble("packetLimit"); checkLoss(insulatedCable); super.readFromNBT(nbtTag); } @Override public Packet getDescriptionPacket() { NBTTagCompound nbtTag = new NBTTagCompound(); this.writeToNBT(nbtTag); //TODO: Get this damn working! return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, 1, nbtTag); } @Override public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) { readFromNBT(packet.func_148857_g()); } @Override public void updateEntity() { if(!internalBuffer.isEmpty()) { MFPacket packet = internalBuffer.remove(); boolean result=false; byte direction; for(int i=0; i<59;i++) { int posNeg = ((int)(Math.random()*%2==0)?1:-1; double randXvel=Math.random()*(2*posNeg); double randYvel=Math.random()*(2*posNeg); double randZvel=Math.random()*(2*posNeg); this.worldObj.spawnParticle("magicCrit", xCoord, yCoord, zCoord, randXvel, randYvel, randZvel); } switch(packet.getType()) { case RESPOND: direction = packet.getOrigin().peek(); result = (direction!=-1); result = pushPacket(packet); break; default: direction = packet.getOrigin().peek(); packet.getOrigin().add(randDir(direction).toByte()); result=pushPacket(packet); break; } } super.updateEntity(); } private I_PipeDirection randDir(byte initDirection) { int randNum=(int)(Math.random()*connections.size()); return connections.get(randNum); } public boolean checkConnections() { boolean result=false; int x,y,z; for(x=-1;x<2;x++) { for(y=-1;y<2;y++) { for(z=-1;z<2;z++) { Block target = worldObj.getBlock(xCoord+x, yCoord+y, zCoord+z); if(target.hasTileEntity(target.getDamageValue(worldObj, xCoord+x, yCoord+y, zCoord+z))&&MFHelper.checkConnectable(worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))) { boolean twoWay = (worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))instanceof I_MFCable; formConnection(twoWay, x,y,z); } } } } return result; } @Override public void formConnection(boolean twoWay, int x, int y, int z) { connections.add(new PipeDirection(x, y, z)); if (twoWay) ((I_MFCable)(worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))).formConnection(false, -x, -y, -z); System.out.println("connection formed"); } @Override public void breakConnection(I_PipeDirection direction) { // if ((worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))instanceof I_MFCable) // ((I_MFCable)(worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))).formConnection(false, -x, -y, -z); // System.out.println("connection removed"); // connections.remove(direction); } @Override public boolean pushPacket(MFPacket packet) { byte direction = packet.getOrigin().peek(); if(packet.getType()==E_MFPacketType.RESPOND) packet.getOrigin().pop(); boolean result= false; int[]origin = {xCoord,yCoord,zCoord}; int[] target = new PipeDirection(direction).getTarget(); for(int i=0;i<3;i++) { target[i]+=origin[i]; } result = this.worldObj.getBlock(target[0], target[1], target[2]).hasTileEntity(0); if(result) result=this.worldObj.getTileEntity(target[0], target[1], target[2])instanceof I_MFSink; if(result) result=((I_MFSink)this.worldObj.getTileEntity(target[0], target[1], target[2])).takePacket(packet); if(!result) powerBleed(packet.getBuffer()); return result; } @Override public boolean canUpdate() { return true; } @Override public double flowLimit() { return packetSizeLimit; } @Override public void powerBleed(double excess) { //add power bleed to chunk atmosphere -> own effects + taint if Thaumcraft installed if(excess>0) System.err.println(""+excess+" MF bled off into atmosphere!\n"); } @Override public double getPacketLimit() { return packetSizeLimit; } @Override public boolean isInsulated() { return insulatedCable; } @Override public boolean isBridged() { return bridgeConnections; } @Override public boolean canDeBridge() { return insulatedCable; } @Override public List<I_PipeDirection> getConnections() { return connections; } } [spoiler=Renderer] package net.RPower.RPowermod.renderers.block; import org.lwjgl.opengl.GL11; import RPower.api.power.cable.I_PipeDirection; import cpw.mods.fml.client.registry.RenderingRegistry; import net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.model.ModelBase; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.client.shader.TesselatorVertexState; import net.minecraft.entity.Entity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; /** * * @author Minothor, Flenix *Renders the card Decks in the world *Adapted from Flenix's Tutorial at: *http://www.minecraftforge.net/wiki/Rendering_a_Techne_Model_as_a_Block */ //TODO: Cancel rendering if not visible //Current Idea: Player.yaw/pitch trigonometry && sky light public class TileEntityFluxCableRenderer extends TileEntitySpecialRenderer { private final ResourceLocation texture; public static int blockRenderId; public static final float pixel = 1.0F/16; public TileEntityFluxCableRenderer() { blockRenderId = RenderingRegistry.getNextAvailableRenderId(); texture = new ResourceLocation(net.RPower.RPowermod.core.RPCore.modid+":textures/blocks/fluxCable.png"); } @Override public void renderTileEntityAt(TileEntity entity, double x, double y, double z, float scale) { //binding the textures Minecraft.getMinecraft().renderEngine.bindTexture(texture); GL11.glPushMatrix(); //initial location (what's up with the 0.5 and 1.5 difference I wonder) GL11.glTranslatef((float) x + 0.5F, (float) y + 0.5F, (float) z + 0.5F); GL11.glDisable(GL11.GL_CULL_FACE); drawHub(); //let LWGL know we're doing more matixy manipulation stuff //rotate to avoid model rendering upside down for (I_PipeDirection connection : ((TileEntityFluxCable)entity).connections) { int[] target = connection.getTarget(); float[] angles = {0,0,0}; if(target[1]!=0) { if((target[0]==0)&&(target[2]==0)) { angles[2]=90F; } else { angles[2]=35F; } } if((target[0]!=0)&&(target[2]!=0)) { angles[0]=45; angles[2]=45; } else { angles[0]=90; angles[2]=90; } angles[0]*=target[0]; angles[1]*=target[1]; angles[2]*=target[2]; drawConnector(angles); } //pop both sections off the render stack GL11.glPopMatrix(); //System.out.println("FOV : "+Minecraft.getMinecraft().gameSettings.fovSetting); GL11.glEnable(GL11.GL_CULL_FACE); } private void drawHub() { Tessellator tessellator = Tessellator.instance; tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(90, 1, 0, 0); //90x tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(90, 1, 0, 0); //180x tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(90, 1, 0, 0); //270x tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(90, 1, 0, 0); GL11.glRotatef(90, 0, 1, 0); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(180, 0, 1, 0); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(90, 0, 1, 0); } private void drawRails(int size) { GL11.glPushMatrix(); GL11.glRotatef(45, 1, 0, 0); Tessellator tessellator = Tessellator.instance; drawRail(size, tessellator); GL11.glRotatef(90, 1, 0, 0); drawRail(size, tessellator); GL11.glRotatef(90, 1, 0, 0); drawRail(size, tessellator); GL11.glRotatef(90, 1, 0, 0); drawRail(size, tessellator); GL11.glRotatef(90, 1, 0, 0); GL11.glRotatef(-45, 1, 0, 0); GL11.glPopMatrix(); } private void drawRail(int size, Tessellator tessellator) { float offset=27.4F; GL11.glRotatef(45F-offset, 1, 0, 0); GL11.glRotatef(-offset, 1, 0, 0); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(0, 0.5*pixel, -2*pixel, size*pixel, 1*pixel); tessellator.addVertexWithUV(size*pixel, 0.5*pixel, -2*pixel, 0*pixel, 0*pixel); tessellator.addVertexWithUV(size*pixel, -0.5*pixel, -2*pixel, 0*pixel, 0*pixel); tessellator.addVertexWithUV(0, -0.5*pixel, -2*pixel, size*pixel, 1*pixel); tessellator.draw(); GL11.glRotatef(offset, 1, 0, 0); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(0, 0.5*pixel, -2*pixel, size*pixel, 2*pixel); tessellator.addVertexWithUV(size*pixel, 0.5*pixel, -2*pixel, 0*pixel, 1*pixel); tessellator.addVertexWithUV(size*pixel, -0.5*pixel, -2*pixel, 0*pixel, 1*pixel); tessellator.addVertexWithUV(0, -0.5*pixel, -2*pixel, size*pixel, 2*pixel); tessellator.draw(); GL11.glRotatef(-45F+offset, 1, 0, 0); } private void drawCore(int size) { GL11.glPushMatrix(); Tessellator tessellator = Tessellator.instance; tessellator.startDrawingQuads(); tessellator.addVertexWithUV(0, 1*pixel, 0, size*pixel, 8*pixel); tessellator.addVertexWithUV(size*pixel, 1*pixel, 0, 0*pixel, 8*pixel); tessellator.addVertexWithUV(size*pixel, -1*pixel, 0, 0*pixel, 6*pixel); tessellator.addVertexWithUV(0, -1*pixel, 0, size*pixel, 6*pixel); tessellator.draw(); GL11.glRotatef(90, 1, 0, 0); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(0, 1*pixel, 0, size*pixel, 8*pixel); tessellator.addVertexWithUV(size*pixel, 1*pixel, 0, 0*pixel, 8*pixel); tessellator.addVertexWithUV(size*pixel, -1*pixel, 0, 0*pixel, 6*pixel); tessellator.addVertexWithUV(0, -1*pixel, 0, size*pixel, 6*pixel); tessellator.draw(); GL11.glRotatef(90, -1, 0, 0); GL11.glPopMatrix(); } private void drawConnector(float[] angle) { int size = 8; if((angle[1]!=90)||(angle[1]!=90)) size+=3; if(((angle[0]!=90)||(angle[2]!=90))&&((angle[0]!=-90)||(angle[2]!=-90))) size+=3; GL11.glRotatef(angle[0], 1, 0, 0); GL11.glRotatef(angle[1], 0, 1, 0); GL11.glRotatef(angle[2], 0, 0, 1); drawCore(size); drawRails(size); GL11.glRotatef(-angle[2], 0, 0, 1); GL11.glRotatef(-angle[1], 0, 1, 0); GL11.glRotatef(-angle[0], 1, 0, 0); } private void adjustLightFixture(World world, int x, int y, int z, Block block) { Tessellator tess = Tessellator.instance; float brightness = block.getLightValue(world, x, y, z); int skyLight = world.getLightBrightnessForSkyBlocks(x, y, z, 0); int modulousModifier = skyLight % 65536; int divModifier = skyLight / 65536; tess.setColorOpaque_F(brightness, brightness, brightness); OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, modulousModifier, divModifier); } } [spoiler=Console Output] [12:11:17] [server thread/INFO]: ForgeDevName[local:E:59a8daed] logged in with entity id 184 at (-348.99236659743696, 4.624356365163005, 1024.041203547941) [12:11:17] [server thread/INFO]: ForgeDevName joined the game Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@312170df connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@312170df connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@312170df connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@7be0e5ee connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@7be0e5ee connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@7be0e5ee connection formed connection formed This pipe has 6 connections. This pipe has 6 connections. Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@16db3e02 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@16db3e02 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@16db3e02 connection formed connection formed This pipe has 6 connections. This pipe has 6 connections. Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@7be0e5ee connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@533052d7 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@7be0e5ee connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@533052d7 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@7be0e5ee connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@533052d7 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@1cf07d10 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@16db3e02 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@1cf07d10 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@16db3e02 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@1cf07d10 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@16db3e02 connection formed connection formed This pipe has 9 connections. This pipe has 9 connections. Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@1cf07d10 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@16db3e02 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@4329acba connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@1cf07d10 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@16db3e02 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@4329acba connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@1cf07d10 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@16db3e02 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@4329acba connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@1cf07d10 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@3bf7e8a connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@4329acba connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@1cf07d10 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@3bf7e8a connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@4329acba connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@1cf07d10 connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@3bf7e8a connection formed connection formed Success! net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable@4329acba connection formed connection formed This pipe has 12 connections. This pipe has 15 connections. This pipe has 9 connections. This pipe has 15 connections. This pipe has 12 connections. This pipe has 15 connections. This pipe has 9 connections. This pipe has 15 connections. [12:13:16] [Client thread/INFO]: [CHAT] Saved screenshot as 2014-08-26_12.13.16.png Result of above testing: https://lh4.googleusercontent.com/-AQwAhw6jNJE/U_xeCFIR-ZI/AAAAAAAAB-Y/Ui_Nkaqezto/w854-h480-no/2014-08-26_12.13.16.png[/img] Mockups of designed behaviours: https://lh6.googleusercontent.com/-N4-qAOds6d4/U_sGZXq5OJI/AAAAAAAAB9w/vRdSYcWbflI/w854-h480-no/2014-08-25_11.43.51.png[/img] https://lh4.googleusercontent.com/-pYd_nllX6ds/U_tKtnjkPyI/AAAAAAAAB-E/qGGlsLewXi0/w854-h480-no/2014-08-25_16.38.51.png[/img] https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 26, 201411 yr Have you looked closely at the code that spawns the pipe? Maybe you accidentally did something wrong? I am the self-nominated Lord of the Mastodons and don't you dare deny it. Also, check out my YouTube channel: https://www.youtube.com/user/DerpDerp44/
August 26, 201411 yr Author The only thing I can see that's obvious is that I forgot to stop the pipe from including itself in the connections, but even after I changed the checkConnection code to ignore the centre block: boolean centre = (x==0)&&(y==0)&&(z==0); if(target.hasTileEntity(target.getDamageValue(worldObj, xCoord+z, yCoord+y, zCoord+z))&&MFHelper.checkConnectable(worldObj.getTileEntity(xCoord+z, yCoord+y, zCoord+z))) { if(!centre){ boolean twoWay = (worldObj.getTileEntity(xCoord+z, yCoord+y, zCoord+z))instanceof I_MFCable; formConnection(twoWay, x,y,z); } } It's still returning 4 connections EDIT: Changed the check to be inside the formConnection() function, it now disregards any that have x,y,z all set to 0. Still struggling to find all the pipes though, it only appears to be detecting pipes that satisfy these relative conditions: (y<0, x>0, z>0) any ideas what's going on? https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 26, 201411 yr I think this may be because you do not have any -'s in your code. There are only +'s, so the code does not register the -'s. I am the self-nominated Lord of the Mastodons and don't you dare deny it. Also, check out my YouTube channel: https://www.youtube.com/user/DerpDerp44/
August 27, 201411 yr Author Cheers for the suggestions and help everyone, after swapping over to Tesselator and handling directions in a class similar to an ENUM I've managed to get it working, the Renderer is a bit of a mess of "if()" statements though, but for now it works: https://lh6.googleusercontent.com/-LgFEnwWolU4/U_2YFF6-3kI/AAAAAAAAB-s/hBZU0QYU_Ws/w854-h480-no/2014-08-27_10.29.42.png[/img] Fixed Abstract Class for PipeDirection (saving and loading to byte array for the NBT was the main issue) package RPower.api.power.cable; public abstract class A_PipeDirection implements I_PipeDirection { protected int[] target = {0,0,0}; public A_PipeDirection(int xOffset, int yOffset, int zOffset) { int[] targetArr= {xOffset,yOffset,zOffset}; setTarget(targetArr); } //TODO: Solve why connections of Y= 1, X&Z=0 evaluate to -89 instead of 111. public A_PipeDirection(byte b) { System.out.println("["+b+"]"); //y = b/100 (nearest whole) int yOffset = (byte)b/100; System.out.println(b+" yO:"+yOffset); //remove the processed value from the byte b-=(100*yOffset); System.out.println(" "+b); if(b<0) b*=-1; //x = (b/10)-1 (again, nearest whole and convert 0-> -1, 1 -> 0, 2 -> 1) int xOffset = (b/10)-1; System.out.println(b+" xO:"+xOffset); //remove the processed value from the byte b-= (10*(xOffset+1)); System.out.println(" "+b); //z = b-1 (converting 0-> -1, 1 -> 0, 2 -> 1) int zOffset = b-1; System.out.println(b+" zO:"+zOffset); int[] targetArr= {xOffset,yOffset,zOffset}; setTarget(targetArr); } @Override public void setTarget(int[] target) { this.target = target; } @Override public int[] getTarget() { return target; } @Override public byte toByte() { byte modifier = (byte) (target[1]<0?-1:1); //=(100*y)+(10*(x+1))+(z+1) byte xRef = (byte) ((modifier*10)*(1+target[0])); System.out.println("Byte xRef:"+xRef); byte yRef = (byte) (100*target[1]); System.out.println("Byte yRef:"+yRef); byte zRef = (byte)(modifier*(1+target[2])); System.out.println("Byte zRef:"+zRef); byte result = (byte) (zRef+xRef+yRef); return result; } @Override public String toJSON() { String result = "\n{"; result+=("\n\t\"targetX\":\""+target[0]+"\","); result+=("\n\t\"targetY\":\""+target[1]+"\","); result+=("\n\t\"targetZ\":\""+target[2]+"\""); result+="\n}\n"; return result; } } Fixed TileEntity (now correctly checks the surrounding 26 blocks for connectable Tiles): package net.RPower.RPowermod.machines.power.cable; import java.util.LinkedList; import java.util.List; import java.util.Queue; import RPower.api.power.E_MFPacketType; import RPower.api.power.I_MFSink; import RPower.api.power.MFHelper; import RPower.api.power.MFPacket; import RPower.api.power.cable.I_MFCable; import RPower.api.power.cable.I_PipeDirection; import net.RPower.RPowermod.core.RPCore; import net.minecraft.block.Block; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.network.play.server.S35PacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.ForgeDirection; public class TileEntityFluxCable extends TileEntity implements I_MFCable { //Connections are an array of [up, Down, North, East, West, South] public List<I_PipeDirection> connections; //whether or not the cable is lossy public boolean insulatedCable; //maximum limit the cable can carry public double packetSizeLimit; //Packets awaiting processing public Queue<MFPacket> internalBuffer; //automatically calculated. public double percentageLoss; //transfer mode, unbridged connections can only cross an intersection in straight lines (may be reserved for advanced cabling) public boolean bridgeConnections; public TileEntityFluxCable() { this(32); } public TileEntityFluxCable(double packetSize) { this(packetSize,false); } public TileEntityFluxCable(double packetSize, boolean insulated) { this(packetSize,insulated,true); } public TileEntityFluxCable(double packetSize, boolean insulated,boolean bridged) { packetSizeLimit= packetSize; insulatedCable=insulated; bridgeConnections=bridged; connections=new LinkedList<I_PipeDirection>(); internalBuffer=new LinkedList<MFPacket>(); checkLoss(insulated); } private void checkLoss(boolean insulated) { if(!insulated) { percentageLoss=(packetSizeLimit/MFPacket.POWERLIMIT); } } @Override public boolean takePacket(MFPacket packet) { double excess=0; if(!insulatedCable) { excess+=(percentageLoss*packet.getBuffer()); packet.setBuffer(packet.getBuffer()-excess); } if(packet.getBuffer()>packetSizeLimit) { excess += packet.getBuffer()-packetSizeLimit; packet.setBuffer(packetSizeLimit); } powerBleed(excess); boolean result=false; result=internalBuffer.add(packet); return result; } @Override public void writeToNBT(NBTTagCompound nbtTag) { byte[] connectionsArr = new byte[connections.size()]; int i =0; for (I_PipeDirection connection: connections) { connectionsArr[i] = connection.toByte(); i++; } nbtTag.setByteArray("connections", connectionsArr); nbtTag.setBoolean("insulated", insulatedCable); nbtTag.setBoolean("bridged", bridgeConnections); nbtTag.setDouble("packetLimit", packetSizeLimit); super.writeToNBT(nbtTag); }; @Override public void readFromNBT(NBTTagCompound nbtTag) { byte[] connectionsArr = nbtTag.getByteArray("connections"); for (byte b : connectionsArr) { I_PipeDirection temp = new PipeDirection(b); connections.add(temp); } insulatedCable=nbtTag.getBoolean("insulated"); bridgeConnections=nbtTag.getBoolean("bridged"); packetSizeLimit=nbtTag.getDouble("packetLimit"); checkLoss(insulatedCable); super.readFromNBT(nbtTag); } @Override public Packet getDescriptionPacket() { NBTTagCompound nbtTag = new NBTTagCompound(); this.writeToNBT(nbtTag); //TODO: Get this damn working! return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, 1, nbtTag); } @Override public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) { readFromNBT(packet.func_148857_g()); } @Override public void updateEntity() { if(!internalBuffer.isEmpty()) { MFPacket packet = internalBuffer.remove(); boolean result=false; byte direction; for(int i=0; i<59;i++) { int posNeg = ((int)(Math.random()*%2==0)?1:-1; double randXvel=Math.random()*(2*posNeg); double randYvel=Math.random()*(2*posNeg); double randZvel=Math.random()*(2*posNeg); this.worldObj.spawnParticle("magicCrit", xCoord, yCoord, zCoord, randXvel, randYvel, randZvel); } switch(packet.getType()) { case RESPOND: direction = packet.getOrigin().peek(); result = (direction!=-1); result = pushPacket(packet); break; default: direction = packet.getOrigin().peek(); packet.getOrigin().add(randDir(direction).toByte()); result=pushPacket(packet); break; } } super.updateEntity(); } private I_PipeDirection randDir(byte initDirection) { int randNum=(int)(Math.random()*connections.size()); return connections.get(randNum); } public boolean checkConnections() { boolean result=false; int x,y,z,i=0; for(y=-1;y<2;y++) { System.out.println("Y Level: "+y); for(x=-1;x<2;x++) { System.out.println("X Position: "+x); for(z=-1;z<2;z++) { System.out.println("Z Position: "+z); i++; Block target = worldObj.getBlock(xCoord+x, yCoord+y, zCoord+z); System.out.print("Test["+i+"] Checking block at ["+(xCoord+x)+","+(yCoord+y)+","+(zCoord+z)+"]"); if(target.hasTileEntity(target.getDamageValue(worldObj, xCoord+x, yCoord+y, zCoord+z))&&MFHelper.checkConnectable(worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))) { System.out.print(" - Valid!"); boolean twoWay = (worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))instanceof I_MFCable; formConnection(twoWay, x,y,z); } System.out.print('\n'); } } System.out.println("================================================================="); } return result; } @Override public void formConnection(boolean twoWay, int x, int y, int z) { if(!(x==0&&y==0&&z==0)) { connections.add(new PipeDirection(x, y, z)); if (twoWay) { ((I_MFCable)(worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))).formConnection(false, -x, -y, -z); worldObj.markBlockForUpdate(xCoord+x, yCoord+y, zCoord+z); } System.out.println("connection formed"); } } @Override public void breakConnection(I_PipeDirection direction) { // if ((worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))instanceof I_MFCable) // ((I_MFCable)(worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))).formConnection(false, -x, -y, -z); // System.out.println("connection removed"); // connections.remove(direction); } @Override public boolean pushPacket(MFPacket packet) { byte direction = packet.getOrigin().peek(); if(packet.getType()==E_MFPacketType.RESPOND) packet.getOrigin().pop(); boolean result= false; int[]origin = {xCoord,yCoord,zCoord}; int[] target = new PipeDirection(direction).getTarget(); for(int i=0;i<3;i++) { target[i]+=origin[i]; } result = this.worldObj.getBlock(target[0], target[1], target[2]).hasTileEntity(0); if(result) result=this.worldObj.getTileEntity(target[0], target[1], target[2])instanceof I_MFSink; if(result) result=((I_MFSink)this.worldObj.getTileEntity(target[0], target[1], target[2])).takePacket(packet); if(!result) powerBleed(packet.getBuffer()); return result; } @Override public boolean canUpdate() { return true; } @Override public double flowLimit() { return packetSizeLimit; } @Override public void powerBleed(double excess) { //add power bleed to chunk atmosphere -> own effects + taint if Thaumcraft installed if(excess>0) System.err.println(""+excess+" MF bled off into atmosphere!\n"); } @Override public double getPacketLimit() { return packetSizeLimit; } @Override public boolean isInsulated() { return insulatedCable; } @Override public boolean isBridged() { return bridgeConnections; } @Override public boolean canDeBridge() { return insulatedCable; } @Override public List<I_PipeDirection> getConnections() { return connections; } public String toJSON() { String result = "\n{"; result+=("\n\t\"tileX\":\""+xCoord+"\","); result+=("\n\t\"tileY\":\""+yCoord+"\","); result+=("\n\t\"tileZ\":\""+zCoord+"\","); result+=("\n\t\"connections\":[\n"); for (I_PipeDirection pipe : connections) { result+=(pipe.toJSON()+",\n"); } result+="]"; result+="\n}\n"; return result; } } Fixed Renderer: package net.RPower.RPowermod.renderers.block; import org.lwjgl.opengl.GL11; import RPower.api.power.cable.I_PipeDirection; import cpw.mods.fml.client.registry.RenderingRegistry; import net.RPower.RPowermod.machines.power.cable.TileEntityFluxCable; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.model.ModelBase; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.client.shader.TesselatorVertexState; import net.minecraft.entity.Entity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; /** * * @author Minothor, Flenix *Renders the card Decks in the world *Adapted from Flenix's Tutorial at: *http://www.minecraftforge.net/wiki/Rendering_a_Techne_Model_as_a_Block */ //TODO: Cancel rendering if not visible //Current Idea: Player.yaw/pitch trigonometry && sky light public class TileEntityFluxCableRenderer extends TileEntitySpecialRenderer { private final ResourceLocation texture; public static int blockRenderId; public static final float pixel = 1.0F/16; public Tessellator tessellator; public TileEntityFluxCableRenderer() { tessellator = Tessellator.instance; blockRenderId = RenderingRegistry.getNextAvailableRenderId(); texture = new ResourceLocation(net.RPower.RPowermod.core.RPCore.modid+":textures/blocks/fluxCable.png"); } @Override public void renderTileEntityAt(TileEntity entity, double x, double y, double z, float scale) { //binding the textures Minecraft.getMinecraft().renderEngine.bindTexture(texture); GL11.glPushMatrix(); //initial location (what's up with the 0.5 and 1.5 difference I wonder) GL11.glTranslatef((float) x + 0.5F, (float) y + 0.5F, (float) z + 0.5F); GL11.glDisable(GL11.GL_CULL_FACE); drawHub(); //let LWGL know we're doing more matixy manipulation stuff //rotate to avoid model rendering upside down for (I_PipeDirection connection : ((TileEntityFluxCable)entity).connections) { int[] target = connection.getTarget(); float[] angles = {0,0,0}; float yMod = (target[0]==0&&target[2]==0)?90F:45F; float xMod=0; float xDir=0; float zDir=0; float zMod=0; if(target[1]==0) xMod=-90F; if(target[0]==0) { xDir=target[2]; xMod=-90F; } if(target[2]==0) { xDir=target[0]; xMod=180F; if(xDir>0) { xMod=0F; } } if(target[0]!=0&&target[2]!=0) { if(target[2]>0) { xDir=1; xMod=-135; if(target[0]>0) { xDir*=-1; xMod=45F; yMod-=10; } } else if(target[0]<0) { zDir=1; xDir=-1; zMod=360F; xMod=225F; yMod-=10; } else if(target[0]>0) { if(target[2]<0) { xDir=1; xMod=45; yMod-=10; } } if(target[0]<0&&target[2]>0) { if(target[1]<0) yMod=35F; if(target[1]>0) yMod=35F; } } angles[0]=zDir*zMod; angles[1]=xDir*xMod; angles[2]=target[1]*yMod; drawConnector(angles); } //pop both sections off the render stack GL11.glPopMatrix(); //System.out.println("FOV : "+Minecraft.getMinecraft().gameSettings.fovSetting); GL11.glEnable(GL11.GL_CULL_FACE); } private void drawHub() { tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(90, 1, 0, 0); //90x tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(90, 1, 0, 0); //180x tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(90, 1, 0, 0); //270x tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(90, 1, 0, 0); GL11.glRotatef(90, 0, 1, 0); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(180, 0, 1, 0); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(2*pixel, 2*pixel, 2*pixel, 4*pixel,1); tessellator.addVertexWithUV(-2*pixel, 2*pixel, 2*pixel, 0,1); tessellator.addVertexWithUV(-2*pixel, -2*pixel, 2*pixel, 0,12*pixel); tessellator.addVertexWithUV(2*pixel, -2*pixel, 2*pixel, 4*pixel,12*pixel); tessellator.draw(); GL11.glRotatef(90, 0, 1, 0); } private void drawRails(int size) { GL11.glPushMatrix(); GL11.glRotatef(45, 1, 0, 0); Tessellator tessellator = Tessellator.instance; drawRail(size, tessellator); GL11.glRotatef(90, 1, 0, 0); drawRail(size, tessellator); GL11.glRotatef(90, 1, 0, 0); drawRail(size, tessellator); GL11.glRotatef(90, 1, 0, 0); drawRail(size, tessellator); GL11.glRotatef(90, 1, 0, 0); GL11.glRotatef(-45, 1, 0, 0); GL11.glPopMatrix(); } private void drawRail(int size, Tessellator tessellator) { float offset=27.4F; GL11.glRotatef(45F-offset, 1, 0, 0); GL11.glRotatef(-offset, 1, 0, 0); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(0, 0.5*pixel, -2*pixel, size*pixel, 1*pixel); tessellator.addVertexWithUV(size*pixel, 0.5*pixel, -2*pixel, 0*pixel, 0*pixel); tessellator.addVertexWithUV(size*pixel, -0.5*pixel, -2*pixel, 0*pixel, 0*pixel); tessellator.addVertexWithUV(0, -0.5*pixel, -2*pixel, size*pixel, 1*pixel); tessellator.draw(); GL11.glRotatef(offset, 1, 0, 0); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(0, 0.5*pixel, -2*pixel, size*pixel, 2*pixel); tessellator.addVertexWithUV(size*pixel, 0.5*pixel, -2*pixel, 0*pixel, 1*pixel); tessellator.addVertexWithUV(size*pixel, -0.5*pixel, -2*pixel, 0*pixel, 1*pixel); tessellator.addVertexWithUV(0, -0.5*pixel, -2*pixel, size*pixel, 2*pixel); tessellator.draw(); GL11.glRotatef(-45F+offset, 1, 0, 0); } private void drawCore(int size) { GL11.glPushMatrix(); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(0, 1*pixel, 0, size*pixel, 8*pixel); tessellator.addVertexWithUV(size*pixel, 1*pixel, 0, 0*pixel, 8*pixel); tessellator.addVertexWithUV(size*pixel, -1*pixel, 0, 0*pixel, 6*pixel); tessellator.addVertexWithUV(0, -1*pixel, 0, size*pixel, 6*pixel); tessellator.draw(); GL11.glRotatef(90, 1, 0, 0); tessellator.startDrawingQuads(); tessellator.addVertexWithUV(0, 1*pixel, 0, size*pixel, 8*pixel); tessellator.addVertexWithUV(size*pixel, 1*pixel, 0, 0*pixel, 8*pixel); tessellator.addVertexWithUV(size*pixel, -1*pixel, 0, 0*pixel, 6*pixel); tessellator.addVertexWithUV(0, -1*pixel, 0, size*pixel, 6*pixel); tessellator.draw(); GL11.glRotatef(90, -1, 0, 0); GL11.glPopMatrix(); } private void drawConnector(float[] angle) { int size = 8; if((angle[1]!=90)||(angle[1]!=90)) size+=3; if(((angle[0]!=90)||(angle[2]!=90))&&((angle[0]!=-90)||(angle[2]!=-90))) size+=3; GL11.glRotatef(angle[0], 1, 0, 0); GL11.glRotatef(angle[1], 0, 1, 0); GL11.glRotatef(angle[2], 0, 0, 1); drawCore(size); drawRails(size); GL11.glRotatef(-angle[2], 0, 0, 1); GL11.glRotatef(-angle[1], 0, 1, 0); GL11.glRotatef(-angle[0], 1, 0, 0); } private void adjustLightFixture(World world, int x, int y, int z, Block block) { float brightness = block.getLightValue(world, x, y, z); int skyLight = world.getLightBrightnessForSkyBlocks(x, y, z, 0); int modulousModifier = skyLight % 65536; int divModifier = skyLight / 65536; tessellator.setColorOpaque_F(brightness, brightness, brightness); OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, modulousModifier, divModifier); } } https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 27, 201411 yr Also, I'd recommend changing the texture to a slightly darker color, because it's burning my eyes, and I don't think your friends really want burnt eyes. I am the self-nominated Lord of the Mastodons and don't you dare deny it. Also, check out my YouTube channel: https://www.youtube.com/user/DerpDerp44/
August 27, 201411 yr Author that's more a combo of the solid-colour testing texture and lighting glitches and I'll tweak those once I've got the mechanics verified. https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 27, 201411 yr Proboably a good idea I am the self-nominated Lord of the Mastodons and don't you dare deny it. Also, check out my YouTube channel: https://www.youtube.com/user/DerpDerp44/
August 27, 201411 yr Author hitting a new bug now I'm afraid, remotely calling the breakConnection() function on adjacent pipes sometimes leaves open ended connections towards the removed pipe. package net.RPower.RPowermod.machines.power.cable; import java.util.LinkedList; import java.util.List; import java.util.Queue; import RPower.api.power.E_MFPacketType; import RPower.api.power.I_MFSink; import RPower.api.power.MFHelper; import RPower.api.power.MFPacket; import RPower.api.power.cable.I_MFCable; import RPower.api.power.cable.I_PipeDirection; import net.RPower.RPowermod.core.RPCore; import net.minecraft.block.Block; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.network.play.server.S35PacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.ForgeDirection; public class TileEntityFluxCable extends TileEntity implements I_MFCable { //Connections are an array of [up, Down, North, East, West, South] public List<I_PipeDirection> connections; //whether or not the cable is lossy public boolean insulatedCable; //maximum limit the cable can carry public double packetSizeLimit; //Packets awaiting processing public Queue<MFPacket> internalBuffer; //automatically calculated. public double percentageLoss; //transfer mode, unbridged connections can only cross an intersection in straight lines (may be reserved for advanced cabling) public boolean bridgeConnections; private double distLimit; public TileEntityFluxCable() { this(32); } public TileEntityFluxCable(double packetSize) { this(packetSize,false); } public TileEntityFluxCable(double packetSize, boolean insulated) { this(packetSize,insulated,true); } public TileEntityFluxCable(double packetSize, boolean insulated,boolean bridged) { packetSizeLimit= packetSize; insulatedCable=insulated; bridgeConnections=bridged; connections=new LinkedList<I_PipeDirection>(); internalBuffer=new LinkedList<MFPacket>(); checkLoss(insulated); distLimit = insulatedCable?(4*packetSize):packetSize; } private void checkLoss(boolean insulated) { if(!insulated) { percentageLoss=(packetSizeLimit/MFPacket.POWERLIMIT); } } @Override public boolean takePacket(MFPacket packet) { double excess=0; if(!insulatedCable) { excess+=(percentageLoss*packet.getBuffer()); packet.setBuffer(packet.getBuffer()-excess); } if(packet.getBuffer()>packetSizeLimit) { excess += packet.getBuffer()-packetSizeLimit; packet.setBuffer(packetSizeLimit); } powerBleed(excess); boolean result=false; result=internalBuffer.add(packet); return result; } @Override public void writeToNBT(NBTTagCompound nbtTag) { byte[] connectionsArr = new byte[connections.size()]; int i =0; for (I_PipeDirection connection: connections) { connectionsArr[i] = connection.toByte(); i++; } nbtTag.setByteArray("connections", connectionsArr); nbtTag.setBoolean("insulated", insulatedCable); nbtTag.setBoolean("bridged", bridgeConnections); nbtTag.setDouble("packetLimit", packetSizeLimit); super.writeToNBT(nbtTag); }; @Override public void readFromNBT(NBTTagCompound nbtTag) { byte[] connectionsArr = nbtTag.getByteArray("connections"); for (byte b : connectionsArr) { I_PipeDirection temp = new PipeDirection(b); connections.add(temp); } insulatedCable=nbtTag.getBoolean("insulated"); bridgeConnections=nbtTag.getBoolean("bridged"); packetSizeLimit=nbtTag.getDouble("packetLimit"); checkLoss(insulatedCable); super.readFromNBT(nbtTag); } @Override public Packet getDescriptionPacket() { NBTTagCompound nbtTag = new NBTTagCompound(); this.writeToNBT(nbtTag); //TODO: Get this damn working! return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, 1, nbtTag); } @Override public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) { readFromNBT(packet.func_148857_g()); } @Override public void updateEntity() { if(!internalBuffer.isEmpty()) { MFPacket packet = internalBuffer.remove(); boolean result=false; byte direction; for(int i=0; i<59;i++) { int posNeg = ((int)(Math.random()*%2==0)?1:-1; double randXvel=Math.random()*(2*posNeg); double randYvel=Math.random()*(2*posNeg); double randZvel=Math.random()*(2*posNeg); this.worldObj.spawnParticle("magicCrit", xCoord, yCoord, zCoord, randXvel, randYvel, randZvel); } switch(packet.getType()) { case RESPOND: direction = packet.getOrigin().peek(); result = (direction!=-1); result = pushPacket(packet); break; default: direction = packet.getOrigin().peek(); packet.getOrigin().add(randDir(direction).toByte()); result=pushPacket(packet); break; } } super.updateEntity(); } private I_PipeDirection randDir(byte initDirection) { I_PipeDirection origin = new PipeDirection(initDirection); origin.invert(); I_PipeDirection newDirection = origin; int attempt = 0; while (!connections.isEmpty()&&attempt<26&&newDirection.equals(origin)) { attempt++; int randNum=(int)(Math.random()*connections.size()); newDirection = connections.get(randNum); } return newDirection; } public boolean checkConnections() { boolean result=false; int x,y,z,i=0; for(y=-1;y<2;y++) { //System.out.println("Y Level: "+y); for(x=-1;x<2;x++) { //System.out.println("X Position: "+x); for(z=-1;z<2;z++) { //System.out.println("Z Position: "+z); i++; Block target = worldObj.getBlock(xCoord+x, yCoord+y, zCoord+z); //System.out.print("Test["+i+"] Checking block at ["+(xCoord+x)+","+(yCoord+y)+","+(zCoord+z)+"]"); if(target.hasTileEntity(target.getDamageValue(worldObj, xCoord+x, yCoord+y, zCoord+z))&&MFHelper.checkConnectable(worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))) { //System.out.print(" - Valid!"); boolean twoWay = (worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))instanceof I_MFCable; formConnection(twoWay, x,y,z); } //System.out.print('\n'); } } //System.out.println("================================================================="); } return result; } @Override public void formConnection(boolean twoWay, int x, int y, int z) { if(!(x==0&&y==0&&z==0)) { connections.add(new PipeDirection(x, y, z)); if (twoWay) { ((I_MFCable)(worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))).formConnection(false, -x, -y, -z); worldObj.markBlockForUpdate(xCoord+x, yCoord+y, zCoord+z); } //System.out.println("connection formed"); worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } } @Override public void breakConnection(boolean twoWay, int x, int y, int z) { if (twoWay&&(worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z))instanceof I_MFCable) { I_MFCable targetTile = (I_MFCable)worldObj.getTileEntity(xCoord+x, yCoord+y, zCoord+z); targetTile.breakConnection(false,-x, -y, -z); worldObj.markBlockForUpdate(xCoord+x, yCoord+y, zCoord+z); } connections.remove(new PipeDirection(x,y,z)); worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } @Override public boolean pushPacket(MFPacket packet) { boolean result= false; if(packet.getType()==E_MFPacketType.RESPOND&&packet.getBuffer()<=0) { packet=null; } if(packet!=null&&packet.getOrigin().size()<=distLimit); { byte direction = packet.getOrigin().peek(); if(packet.getType()==E_MFPacketType.RESPOND) packet.getOrigin().pop(); int[]origin = {xCoord,yCoord,zCoord}; int[] target = new PipeDirection(direction).getTarget(); for(int i=0;i<3;i++) { target[i]+=origin[i]; } result = this.worldObj.getBlock(target[0], target[1], target[2]).hasTileEntity(0); if(result) result=this.worldObj.getTileEntity(target[0], target[1], target[2])instanceof I_MFSink; if(result) result=((I_MFSink)this.worldObj.getTileEntity(target[0], target[1], target[2])).takePacket(packet); if(!result) powerBleed(packet.getBuffer()); } return result; } @Override public boolean canUpdate() { return true; } @Override public double flowLimit() { return packetSizeLimit; } @Override public void powerBleed(double excess) { //add power bleed to chunk atmosphere -> own effects + taint if Thaumcraft installed if(excess>0) System.err.println(""+excess+" MF bled off into atmosphere!\n"); } @Override public double getPacketLimit() { return packetSizeLimit; } @Override public boolean isInsulated() { return insulatedCable; } @Override public boolean isBridged() { return bridgeConnections; } @Override public boolean canDeBridge() { return insulatedCable; } @Override public List<I_PipeDirection> getConnections() { return connections; } public String toJSON() { String result = "\n{"; result+=("\n\t\"tileX\":\""+xCoord+"\","); result+=("\n\t\"tileY\":\""+yCoord+"\","); result+=("\n\t\"tileZ\":\""+zCoord+"\","); result+=("\n\t\"connections\":[\n"); for (I_PipeDirection pipe : connections) { result+=(pipe.toJSON()+",\n"); } result+="]"; result+="\n}\n"; return result; } @Override public void breakAllConnections() { for (I_PipeDirection direction : connections) { int[] target = direction.getTarget(); breakConnection(true, target[0], target[1], target[2]); } } } package RPower.api.power.cable; import net.RPower.RPowermod.machines.power.cable.PipeDirection; public abstract class A_PipeDirection implements I_PipeDirection { protected int[] target = {0,0,0}; public A_PipeDirection(int xOffset, int yOffset, int zOffset) { int[] targetArr= {xOffset,yOffset,zOffset}; setTarget(targetArr); } //TODO: Solve why connections of Y= 1, X&Z=0 evaluate to -89 instead of 111. public A_PipeDirection(byte b) { //System.out.println("["+b+"]"); //y = b/100 (nearest whole) int yOffset = (byte)b/100; //System.out.println(b+" yO:"+yOffset); //remove the processed value from the byte b-=(100*yOffset); //System.out.println(" "+b); if(b<0) b*=-1; //x = (b/10)-1 (again, nearest whole and convert 0-> -1, 1 -> 0, 2 -> 1) int xOffset = (b/10)-1; //System.out.println(b+" xO:"+xOffset); //remove the processed value from the byte b-= (10*(xOffset+1)); //System.out.println(" "+b); //z = b-1 (converting 0-> -1, 1 -> 0, 2 -> 1) int zOffset = b-1; //System.out.println(b+" zO:"+zOffset); int[] targetArr= {xOffset,yOffset,zOffset}; setTarget(targetArr); } @Override public void setTarget(int[] target) { this.target = target; } @Override public int[] getTarget() { return target; } @Override public byte toByte() { byte modifier = (byte) (target[1]<0?-1:1); //=(100*y)+(10*(x+1))+(z+1) byte xRef = (byte) ((modifier*10)*(1+target[0])); //System.out.println("Byte xRef:"+xRef); byte yRef = (byte) (100*target[1]); //System.out.println("Byte yRef:"+yRef); byte zRef = (byte)(modifier*(1+target[2])); //System.out.println("Byte zRef:"+zRef); byte result = (byte) (zRef+xRef+yRef); return result; } @Override public String toJSON() { String result = "\n{"; result+=("\n\t\"targetX\":\""+target[0]+"\","); result+=("\n\t\"targetY\":\""+target[1]+"\","); result+=("\n\t\"targetZ\":\""+target[2]+"\""); result+="\n}\n"; return result; } @Override public void invert() { int[] newTarget = {-target[0],-target[1],-target[2]}; target = newTarget; } @Override public boolean equals(Object obj) { if (obj==null||!(obj instanceof I_PipeDirection)) return false; return ((I_PipeDirection)obj).toByte()==this.toByte(); } } https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 27, 201411 yr Try adding -'s sometime. It helps, believe me. I am the self-nominated Lord of the Mastodons and don't you dare deny it. Also, check out my YouTube channel: https://www.youtube.com/user/DerpDerp44/
August 27, 201411 yr Author Please could you elaborate on that? I'm looking through the break connection code and I'm inverting the relative coords in all the right places as far as I can see. https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 28, 201411 yr As far as I could see, you only had things such as Xcoord + x, no Xcoord - x anywhere. I think this may be your problem, but if it is not, then I am completely out of suggestions. I am the self-nominated Lord of the Mastodons and don't you dare deny it. Also, check out my YouTube channel: https://www.youtube.com/user/DerpDerp44/
August 28, 201411 yr Author Ah, yeah, that's because the x value is the relative value from -1 to 1, so xCoord + (-1) is the same as xCoord -1. I'm thinking of adding a cleanUp() function that can be marked to run on block update, see if that helps. https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.