Jump to content

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


derf6060

Recommended Posts

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.

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

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.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I'm using Modrinth as a launcher for a forge modpack on 1.20.1, and can't diagnose the issue on the crash log myself. Have tried repairing the Minecraft instillation as well as removing a few mods that have been problematic for me in the past to no avail. Crash log is below, if any further information is necessary let me know. Thank you! https://paste.ee/p/k6xnS
    • Hey folks. I am working on a custom "Mecha" entity (extended from LivingEntity) that the player builds up from blocks that should get modular stats depending on the used blocks. e.g. depending on what will be used for the legs, the entity will have a different jump strength. However, something unexpected is happening when trying to override a few of LivingEntity's functions and using my new own "Mecha" specific fields: instead of their actual instance-specific value, the default value is used (0f for a float, null for an object...) This is especially strange as when executing with the same entity from a point in the code specific to the mecha entity, the correct value is used. Here are some code snippets to better illustrate what I mean: /* The main Mecha class, cut down for brevity */ public class Mecha extends LivingEntity { protected float jumpMultiplier; //somewhere later during the code when spawning the entity, jumpMultiplier is set to something like 1.5f //changing the access to public didn't help @Override //Overridden from LivingEntity, this function is only used in the jumpFromGround() function, used in the aiStep() function, used in the LivingEntity tick() function protected float getJumpPower() { //something is wrong with this function //for some reason I can't correctly access the fields and methods from the instanciated entity when I am in one of those overridden protected functions. this is very annoying LogUtils.getLogger().info(String.valueOf(this.jumpMultiplier))) //will print 0f return this.jumpMultiplier * super.getJumpPower(); } //The code above does not operate properly. Written as is, the entity will not jump, and adding debug logs shows that when executing the code, the value of this.jumpMultiplier is 0f //in contrast, it will be the correct value when done here: @Override public void tick() { super.tick(); //inherited LivingEntity logic //Custom logic LogUtils.getLogger().info(String.valueOf(this.jumpMultiplier))) //will print 1.5f } } My actual code is slightly different, as the jumpMuliplier is stored in another object (so I am calling "this.legModule.getJumpPower()" instead of the float), but even using a simple float exactly like in the code above didn't help. When running my usual code, the object I try to use is found to be null instead, leading to a crash from a nullPointerException. Here is the stacktrace of said crash: The full code can be viewed here. I have found a workaround in the case of jump strength, but have already found the same problem for another parameter I want to do, and I do not understand why the code is behaving as such, and I would very much like to be able to override those methods as intended - they seemed to work just fine like that for vanilla mobs... Any clues as to what may be happening here?
    • Please delete post. Had not noticed the newest edition for 1.20.6 which resolves the issue.
    • https://paste.ee/p/GTgAV Here's my debug log, I'm on 1.18.2 with forge 40.2.4 and I just want to get it to work!! I cant find any mod names in the error part and I would like some help from the pros!! I have 203 mods at the moment.
  • Topics

×
×
  • Create New...

Important Information

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