Jump to content

[1.10.2] I've having an issue with the Packets. [SOLVED]


Recommended Posts

Posted

What I'm trying to is push information about my internal FluidTank in my tank's TileEntity from server to the client using forges Packet api, but for some reason its calling the setTank method on the server side rather than the client side. Here is some snippets of code from my source. I'll also post a link to the repo as well.

 

PacketHandler:

// Tank Fluid Update
INSTANCE.registerMessage(PacketTankFluidUpdate.Handler.class, PacketTankFluidUpdate.class, nextID(), Side.CLIENT);

PacketTankFluidUpdate and PacketTankFluidUpdate.Handler:

public class PacketTankFluidUpdate implements IMessage {

private int dimension;
private BlockPos pos;
// Tank 
private FluidTank tank = new FluidTank();

public PacketTankFluidUpdate() {}

public PacketTankFluidUpdate(World world, BlockPos pos, FluidTank tank) {
	this.dimension = world.provider.getDimension();
	this.pos = pos;
	this.tank = tank;
}

@Override
public void fromBytes(ByteBuf buf) {
	PacketBuffer buff = new PacketBuffer(buf);
	this.dimension = buff.readInt();
	this.pos = buff.readBlockPos();
	try {
		this.tank.readFromNBT(buff.readNBTTagCompoundFromBuffer());
	} catch (IOException e) {
		e.printStackTrace();
	}
}

@Override
public void toBytes(ByteBuf buf) {
	PacketBuffer buff = new PacketBuffer(buf);
	buff.writeInt(this.dimension);
	buff.writeBlockPos(this.pos);
	NBTTagCompound comp = new NBTTagCompound();
	tank.writeToNBT(comp);
	buff.writeNBTTagCompoundToBuffer(comp);
}

public void onMessageFromServer(MessageContext ctx) {
	World world = DimensionManager.getWorld(this.dimension);
	if(world != null) {
		TileEntity entity = world.getTileEntity(pos);

		if(entity instanceof TileEntityTank) {
			TileEntityTank tank = (TileEntityTank)entity;
			tank.setTank(this.tank);
		}
	}
}

public static class Handler implements IMessageHandler<PacketTankFluidUpdate, IMessage> {

	@Override
	public IMessage onMessage(PacketTankFluidUpdate message, MessageContext ctx) {

		if(ctx.side == Side.CLIENT) {
			message.onMessageFromServer(ctx);
		}

		return null;
	}

}


}

TileEntityTank:

private void sendToClient() {
PacketHandler.INSTANCE.sendToAll(new PacketTankFluidUpdate(this.worldObj, this.pos, this.tank));
}

 

Repo Link: https://github.com/aod6060/BTAWC

 

I'm thinking it could be me doing it backwards but I could be wrong.

Posted

Thanks for the fast reply diesieben07. Pretty much DimesionalManager only runs server . Ok I'm going noting that when I'm sending info to the client.

 

Hmm, also about the warning from the document does that mean I can't send info from server (Server Side TileEntity of some kind) to the client (change Client Side TileEntity and GuiContainer reads from Client Side TileEntity) from the packet api?

Posted

Yeah that's the warning box that I read. I know that you can check and see what Side I'm on. I'm using the context objects side field and checking if I'm on the client side or not. I my problem was using the DimesionManager which was getting an instance of the WorldServer object. Sorry for the confusing question diesieben07.

Posted

I fixed it. I was using the wrong World object. I should have been using Minecraft.getInstance().theWorld instead of the DimensionalManager lol. Silly me. Thanks for the help diesieben07. I'm going to mark this as solved.

Posted

Yeah I forgot this is what I changed in the source code if anyone is having the same issue.

 

public class PacketTankFluidUpdate implements IMessage, Runnable {

private int dimension;
private BlockPos pos;
// Tank 
private FluidTank tank = new FluidTank();

public PacketTankFluidUpdate() {}

public PacketTankFluidUpdate(World world, BlockPos pos, FluidTank tank) {
	this.dimension = world.provider.getDimension();
	this.pos = pos;
	this.tank = tank;
}

@Override
public void fromBytes(ByteBuf buf) {
	PacketBuffer buff = new PacketBuffer(buf);
	this.dimension = buff.readInt();
	this.pos = buff.readBlockPos();
	try {
		this.tank.readFromNBT(buff.readNBTTagCompoundFromBuffer());
	} catch (IOException e) {
		e.printStackTrace();
	}
}

@Override
public void toBytes(ByteBuf buf) {
	PacketBuffer buff = new PacketBuffer(buf);
	buff.writeInt(this.dimension);
	buff.writeBlockPos(this.pos);
	NBTTagCompound comp = new NBTTagCompound();
	tank.writeToNBT(comp);
	buff.writeNBTTagCompoundToBuffer(comp);
}

public static class Handler implements IMessageHandler<PacketTankFluidUpdate, IMessage> {

	@Override
	public IMessage onMessage(PacketTankFluidUpdate message, MessageContext ctx) {

		if(ctx.side == Side.CLIENT) {
			Minecraft.getMinecraft().addScheduledTask(message);
		}

		return null;
	}

}

@Override
public void run() {
	World world = Minecraft.getMinecraft().theWorld;

	if(world != null) {
		TileEntity entity = world.getTileEntity(pos);

		if(entity instanceof TileEntityTank) {
			TileEntityTank tank = (TileEntityTank)entity;
			tank.setTank(this.tank);
		}
	}
}
}

Posted

Your code is still broken because you are still not following the warning box.

This code will randomly fail with weird exceptions or unexpected behavior, because you are interacting with non-threadsafe code from a thread it is not designed to be interact with from.

 

What do you mean? I'm following the warning and I'm using the scheduled task in the static Handler class. I haven't had any issues on my end with. If you did testing with it can you please post the stack trace of it so I can look at it?

 


	@Override
	public IMessage onMessage(PacketTankFluidUpdate message, MessageContext ctx) {

		if(ctx.side == Side.CLIENT) {
			Minecraft.getMinecraft().addScheduledTask(message);
		}

		return null;
	}

 

Hi

 

This example project might be of use

https://github.com/TheGreyGhost/MinecraftByExample

see example mbe60 which shows how to send messages back and forth between client and server

 

Also this page explaining it in a bit more detail

http://greyminecraftcoder.blogspot.com.au/2015/01/thread-safety-with-network-messages.html

 

-TGG

 

Thanks for the code dude. I took a look and it will help me generalize packets later on.

Posted

Its cool dude. I agree with you that its probably not the best way to go about it. Its simply a hot fix for the moment. I'm trying to make a more general routine that would make the data inside the message abstract so the packets can be more ambiguous. Lets say reduce the amount of Packet implementations down to 2 different variants. One packet that will be used to client to server communication and the other is server to client communication. The data portion is were the Runnable stuff will happen. I'm just trying to find a way to decouple data from the message. I'll probably post the system at a later date.

Posted

That is not as good of an idea as you might think, because it will for sure increase data traffic.

Thats probably true. I'm really just doing this for my sense of curiosity. I just want to see if I can do or not. From the results I have at the moment it can be done. :)

 

I agree that it will increase traffic. I'm going to try and identity bottle necks that will cause a ton of network traffic. For example my six sided tank I'm working on has 2 packet that are sent from both the its TileEntity and GuiContainer. Ones for updating the Server Side FluidTank with the Client Side Fluid Tank. What I would do is find the areas were the Server Side Tank needs an update. Those packets will need to be sent when the tank is fill or draining from one of the sides of the block or if a user files and empties a bucket.

 

For the other Packet which aids with configuring the sides of the block to fill and drain the tank from a side of the block. The only time when this happens if the user press a button in the gui to change the configuration. 

 

Plus I'm just playing around with Minecraft modding. My mod is experimental anyway. If the mod was a bigger mod that requires a ton of maintenance or appeal to a ton of Minecraft users then I would change my tone about it. I focus more on the polish factor and optimize code so the to keep UPS issues down. Enough of this silly wall of text. Take it easy man.

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.

Announcements



×
×
  • Create New...

Important Information

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