August 28, 201411 yr Could work. I am the self-nominated Lord of the Mastodons and don't you dare deny it. Also, check out my YouTube channel: https://www.youtube.com/user/DerpDerp44/
August 28, 201411 yr Check if the break is performed serverSide (because the server overwrites the client for tile entities). Use world.isRemote to see that. BTW, where is that method called? I can't find it.. Check out my blog! http://www.whov.altervista.org
August 28, 201411 yr Author I catch the break block in the block class and tell the tileEntity to run the breakAllConnections() method before calling the superclass break method. Code: https://github.com/BackSpace47/main/blob/PowerSystem_V2/java/net/RPower/RPowermod/machines/power/cable/BlockFluxCable.java https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 28, 201411 yr Does breakConnection run smoothly or you get some weird behaviour? Also, in breakAllConnections getTarget returns an object with x, y, z of the pipe this pipe connects to, right? connections.contains might be a problem, because I believe it uses equals to check if they are the same object, and they might not be for some reason. Either overwrite equals for PipeDirection or check for the coordinates individually (I suggest last one). Check out my blog! http://www.whov.altervista.org
August 28, 201411 yr Author I haven't been able to test the single function yet, just the removal of a pipe with only one connection. As for the test, I overrode the equals function with a test that checks the results of each connection's toByte() method so I'm evaluating the direction rather than the object in memory. As far as I can tell, the server and client entities desync, but the server side maintains the correct number while meaning that the pipes client side can behave in unintended ways since packets are transient and don't sync. One solution will be to make packet handling server side only and sync the tile entities when the server ones receive a packet. Still left with the visual artifacts client side though. https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 28, 201411 yr Wow, even with the issues you are currently having, this is all really cool! I hope I get as good as you guys one day
August 28, 201411 yr Author I'm not really that good, to be honest, before this year I hadn't really touched Java since 2007. https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 28, 201411 yr Hang on, if it's just a tile entity sync issue this should fix it (as long as Write and Read NBT are complete). Put these in your tile entity @Override public Packet getDescriptionPacket() {//sends packet Packet packet = super.getDescriptionPacket(); NBTTagCompound tag = packet != null ? ((S35PacketUpdateTileEntity)packet).func_148857_g() : new NBTTagCompound(); writeToNBT(tag); return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, 1, tag); } @Override public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {//receives the packet super.onDataPacket(net, pkt); NBTTagCompound tag = pkt.func_148857_g(); readFromNBT(tag); } Check out my blog! http://www.whov.altervista.org
August 28, 201411 yr Author Cheers for pointing out some of the points that I'd missed in the datapacket methods, I've also added in debug code to check the side that's desyncing and it is indeed the client-side that isn't updating it's connections list, server side it cleaning up just fine it would seem. I've added in your changes in the datapacket methods, but the desync is still rearing it's ugly head I'm afraid. Here's the TileEntity class as it stands currently: package net.RPower.RPowermod.machines.power.cable; import java.util.LinkedList; import java.util.List; import java.util.Queue; import RPower.api.power.block.I_MFSink; import RPower.api.power.block.cable.I_MFCable; import RPower.api.power.block.cable.I_PipeDirection; import RPower.api.power.core.E_MFPacketType; import RPower.api.power.core.MFHelper; import RPower.api.power.core.MFPacket; 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); } //Fixed by Whov @Override public Packet getDescriptionPacket() { Packet packet = super.getDescriptionPacket(); NBTTagCompound nbtTag = packet != null ? ((S35PacketUpdateTileEntity)packet).func_148857_g() : new NBTTagCompound(); writeToNBT(nbtTag); this.writeToNBT(nbtTag); //TODO: Get this damn working! return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, 1, nbtTag); } //Fixed by Whov @Override public void onDataPacket(NetworkManager networkManager, S35PacketUpdateTileEntity packet) { super.onDataPacket(networkManager, 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; } @Override 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 synchronized 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 synchronized void breakConnection(boolean twoWay, int x, int y, int z) { I_PipeDirection targetConnector = new PipeDirection(x,y,z); if(connections.contains(targetConnector)) { System.out.println("Connector found..."); System.out.println("Remove operation was "+(connections.remove(targetConnector)?"":"un")+"successful."); } 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); } 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() { System.out.println("Getting "+(worldObj.isRemote?"Client":"Server")+" connections"); 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() { int conNum=connections.size(); for (int i= 0; i<conNum;i++) { int[] target = connections.get(0).getTarget(); breakConnection(true, target[0], target[1], target[2]); } } } https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 28, 201411 yr In your getDescriptionPacket method, your writing twice to NBT. I don't know if that causes the issue, but you might want to fix it. Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support. 1.12 -> 1.13 primer by williewillus. 1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support. http://www.howoldisminecraft1710.today/
August 28, 201411 yr Author Cheers for pointing that out Lars, I've cleaned that up and I'm wondering if I can force the client side to resync in any other way... I'll do some more research over the weekend. Cheers again to everyone for all the help and suggestions so far though! (these forums actually help keep me motivated and ambitious) https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
August 28, 201411 yr Actually, I got it wrong. The server overrides the client. Always. Unless, before that happens, you send that packet using those 2 methods to update the server before it can override the client. If the pipes are wrong in the client, they are either wrong in the server too or the custom renderer is doing something wrong (maybe using old data saved in a field instead of grabbing new one each tick? That would not be really good practice anyway, at least if it's just a intArray). Check out my blog! http://www.whov.altervista.org
August 30, 201411 yr Author Currently the server is keeping the correct connections data and it's the client that's out of sync, I'm shunting all the connection making/breaking/checking code out of the tile entities now and into static methods in the MFHelper api class. Partly to centralize control so that one fix works for all, partly so that I'm not duplicating whole methods for each TE. I'll keep you guys posted if I manage to solve it or not. Cheers again to everyone for the suggestions, help and support! https://lh6.googleusercontent.com/-z5frUimWWu0/U4Wuz9xle4I/AAAAAAAABsE/q3eMXJIDXIM/s800/EmeraldCasinoSig.png[/img]
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.