Jump to content

[1.7.10] Issues with Pipe connections (mechanical)


Minothor

Recommended Posts

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

Link to comment
Share on other sites

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!

 

width=800 height=449https://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;
}

}

 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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/

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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);
}

 

width=800 height=449https://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)

Link to comment
Share on other sites

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/

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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/

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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:

width=800 height=449https://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:

width=800 height=449https://lh6.googleusercontent.com/-N4-qAOds6d4/U_sGZXq5OJI/AAAAAAAAB9w/vRdSYcWbflI/w854-h480-no/2014-08-25_11.43.51.png[/img]

width=800 height=449https://lh4.googleusercontent.com/-pYd_nllX6ds/U_tKtnjkPyI/AAAAAAAAB-E/qGGlsLewXi0/w854-h480-no/2014-08-25_16.38.51.png[/img]

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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:

 

width=800 height=449https://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);
}

}

Link to comment
Share on other sites

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();
}
}

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.