Jump to content

[1.7.10] Server to Client Packet Problem


bluedart

Recommended Posts

So I've been working on a 1.7.10 mod recently and I've had to adapt to some new methods.  I've read some tutorials on this subject and googled just about everything I can think of to try and figure this out, but to no avail.  What appears to be happening in my program is that while I have the ability to send packets from the Client to the Server, I do not have the ability to send packets from the Server to the Client.  This is very confusing.  As far as I can tell I have set everything up in the correct fashion for Server to Client packets to be possible.  Let's take a look at some code.  I'll be truncating irrelevant bits to save space.

 

The main mod class.  The important thing here is that I create and store the SimpleNetworkWrapper here in the preInit() method.

@Mod(modid = ProjectAlchemy.ID, version = ProjectAlchemy.VERSION)
public class ProjectAlchemy
{
public static final String ID = "Project_Alchemy";
public static final String VERSION = "Alpha_0.0.0.1";

public static SimpleNetworkWrapper channel;

@Instance("Project_Alchemy")
public static ProjectAlchemy INSTANCE = new ProjectAlchemy();

//public static Logger log = Logger.getLogger("Project_Alchemy", ProjectAlchemy.class);

@SidedProxy(clientSide = "pa.main.CommonProxyClient", serverSide = "pa.main.CommonProxy")
public static CommonProxy proxy = new CommonProxy();

@EventHandler
public void preInit(FMLPreInitializationEvent event)
{
	channel = NetworkRegistry.INSTANCE.newSimpleChannel(ID);
	proxy.preInit(event.getModConfigurationDirectory(), this);
}
}

 

This code registers the messages.  It's in a different file at the moment, but I've been moving it around.  It's worked exactly the same in any location.

protected void registerPackets()
{
ProjectAlchemy.channel.registerMessage(PacketClipButton.Handler.class, PacketClipButton.class,
	PacketIDs.CLIP_BUTTON, Side.SERVER);
ProjectAlchemy.channel.registerMessage(PacketClipNEI.Handler.class, PacketClipNEI.class,
	PacketIDs.CLIP_NEI, Side.SERVER);
ProjectAlchemy.channel.registerMessage(PacketClipOpen.Handler.class, PacketClipOpen.class,
	PacketIDs.CLIP_OPEN, Side.SERVER);
ProjectAlchemy.channel.registerMessage(PacketRename.Handler.class, PacketRename.class,
	PacketIDs.RENAME, Side.SERVER);
ProjectAlchemy.channel.registerMessage(PacketMachineAccess.Handler.class, PacketMachineAccess.class,
	PacketIDs.MACHINE_ACCESS, Side.SERVER);
ProjectAlchemy.channel.registerMessage(PacketPowerupSync.Handler.class, PacketPowerupSync.class,
	PacketIDs.LEAF_SYNC, Side.CLIENT);
ProjectAlchemy.channel.registerMessage(PacketLeafFlutter.Handler.class, PacketLeafFlutter.class,
	PacketIDs.LEAF_FLUTTER, Side.SERVER);
}

 

CommonProxy houses the actual method that I call to send packets.

public class CommonProxy
{
public void sendPacket(DartPacket packet)
{
	System.out.println("Packet: " + packet.toString());

	if (packet != null && packet.getToClient())
	{
		if (packet.isDimPacket())
		{
			ProjectAlchemy.channel.sendToDimension(packet, packet.getDimID());
			//System.out.println("Send packet to dim: " + packet.getDimID() + ", " + packet.toString() + ", ");
		}  else if (packet.getLocation() != null)
		{
			ProjectAlchemy.channel.sendToAllAround(packet, packet.getLocation());
		}else if (packet.getReceiver() != null)
		{
			EntityPlayer receiver = EntityUtils.getPlayerByName(packet.getReceiver());
			ProjectAlchemy.channel.sendTo(packet, (EntityPlayerMP)receiver);
		}
	}
}

public boolean isSimulating(World world)
{
	return true;
}
}

 

CommonProxyClient has the client-side version of the previous method.:

public class CommonProxyClient extends CommonProxy
{
@Override
public boolean isSimulating(World world)
{
	return (world != null) ? !world.isRemote : false;
}

@Override
public void sendPacket(DartPacket packet)
{
	//super.sendPacket(packet);

	if (packet != null && !packet.getToClient())
		ProjectAlchemy.channel.sendToServer(packet);
}
}

 

My custom Packet base, DartPacket:

public abstract class DartPacket implements IMessage
{
protected String receiver;
protected int dimensionID;

protected TargetPoint point;

public DartPacket() {}

public abstract boolean getToClient();
public abstract boolean isDimPacket();

public int getDimID()
{
	return dimensionID;
}

public String getReceiver()
{
	return receiver;
}

public TargetPoint getLocation()
{
	return point;
}

@Override
public void fromBytes(ByteBuf buf)
{
	try
	{
		if (isDimPacket())
			dimensionID = buf.readByte();

		int nameSize = (int)buf.readByte();

		if (nameSize > 0)
		{
			this.receiver = "";
			for (int i = 0; i < nameSize; i ++)
				receiver += buf.readChar();
		}

		if (buf.readBoolean())
			this.point = new TargetPoint(buf.readInt(), buf.readDouble(),
				buf.readDouble(), buf.readDouble(), buf.readDouble());
	} catch (Exception e) { DebugUtils.printError(e); }
}

@Override
public void toBytes(ByteBuf buf)
{
	if (receiver == null)
		receiver = "";

	try
	{
		if (isDimPacket())
			buf.writeByte(dimensionID);

		buf.writeByte(receiver != null ? receiver.length() : 0);
		for (int i = 0; i < receiver.length(); i ++)
			buf.writeChar(receiver.charAt(i));

		buf.writeBoolean(point != null);
		if (point != null)
		{
			buf.writeInt(point.dimension);
			buf.writeDouble(point.x);
			buf.writeDouble(point.y);
			buf.writeDouble(point.z);
			buf.writeDouble(point.range);
		}
	} catch (Exception e) { DebugUtils.printError(e); }
}
}

 

The Packet in question:

public class PacketPowerupSync extends DartPacket
{
private boolean hasLeaf;

public PacketPowerupSync() {}

public PacketPowerupSync(EntityPlayer player)
{
	hasLeaf = EntityUtils.hasLeaf(player);
	receiver = player.getCommandSenderName();

	this.dimensionID = player.worldObj.provider.dimensionId;
}

@Override
public boolean getToClient() { return true; }
@Override
public boolean isDimPacket() { return true; }

@Override
public void toBytes(ByteBuf buf)
{
	super.toBytes(buf);

	buf.writeBoolean(hasLeaf);
}

@Override
public void fromBytes(ByteBuf buf)
{
	super.fromBytes(buf);

	hasLeaf = buf.readBoolean();
}

public static class Handler implements IMessageHandler<PacketPowerupSync, IMessage>
{
	//@SideOnly(Side.CLIENT)
	@Override
	public IMessage onMessage(PacketPowerupSync message, MessageContext ctx)
	{
		EntityPlayer player = EntityUtils.getPlayerByName(message.receiver);

		System.out.println("Packet received.");

		if (player != null)
		{
			System.out.println("Player not null: " + player.getCommandSenderName() + " Side: " + ProjectAlchemy.proxy.isSimulating(player.worldObj));

			System.out.println("Leaf: " + message.hasLeaf);

			if (message.hasLeaf)
				EntityUtils.giveLeaf(player);
			else
				EntityUtils.takeLeaf(player);
		}

		return null;
	}
}
}

 

I call the common proxy's sendPacket(DartPacket) method to send a packet from wherever I need to.  The custom packet base I use forces me to specify manually in each packet I create what type it is.  I do this so that I can simply call one method and pass the packet for ease of use and extensibility.

 

I've been trying to debug this for the past two days, so I've tried a great deal of other permutations for this setup.  I've tried manually calling channel.sendToAll(), channel.sendToAllAround(), channel.setToDimension() both through and not through the proxy as well as on the server and on the client just in case.  There seems to be no iteration of this where the packet actually reaches the client.

 

Here's what I do know: the server is properly calling and creating the packet to send to the client.  However it simply just does not reach.  Also, if I allow the client proxy to call its super's method (which I did for testing purposes) it will somehow send the packet from the server to the server.  At that point the logic seems to work properly and set the data on the server that the server just attempted to send to the client.  Neat!  But not entirely useful...

 

I hope to Giygas I'm missing something simple, but I just can't mess with this anymore - I'm getting nowhere.  Thank you for any help you can provide.

Link to comment
Share on other sites

This isn't related to your problem:

 

public static ProjectAlchemy INSTANCE = new ProjectAlchemy();

 

But don't set the instance yourself.  Forge is just going to overwrite it.

 

Your problem likely has to do with having your server->client and client->server packet method as the same method in your proxy.  When you're in Single Player, only one of those two can exist at a time, so it'll be the client proxy, which does not call super() and thus cannot handle server->client packets.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

Thanks for the help, Draco.  I had actually already tried that and a few other things, but that wasn't even the main issue.  Although I am using separate methods now since that was also a problem.  Turns out it wasn't having a problem sending the packet to the client, it's just that the logic in the IMessageHandler of the packet was off.  I was so distracted by debug output I wasn't expecting that I didn't even give the real problem a second look.  Testing this on a server is what actually brought it to light.  Turns out I was grabbing a multiplayer version of the player object, which is okay on the internal server, but throws an error when you connect to a real one; which of course made me realize the issue.  Anyway, that version of the player already had the data set to what I wanted to change it to, so that obviously did nothing.  It's working fine now, and I can finally get back to making progress.  Thanks again!

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



×
×
  • Create New...

Important Information

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