Jump to content

[1.7.10] A question about packets


Thornack

Recommended Posts

Hi everyone,

 

I want to update my players IEEP from a gui when the player does something. Specifically, I want to update my players party when the player swaps the position of the party members in his party. Example if i have a party member in slot 1 and a party memeber in slot 2 I want to swap them so that they are reversed. For simplicity I currently use the onItemRightClick method of a generic item to call my swap party members method. If i call my swap method server side then using the following packet everything updates beautifully and is persistent. Now I am not sure what to do when updating the other direction client to server.

 

the swap method in my IEEP class

public void swapPartyMembers(int slotOne, int slotTwo){
	NBTTagCompound tempSlot = partyNbt[slotOne];
	partyNbt[slotOne] = partyNbt[slotTwo];
	partyNbt[slotTwo] = tempSlot;
	PacketOverlord.sendTo(new PacketSyncPlayerParty((EntityPlayer) entityPlayer),(EntityPlayerMP) entityPlayer);
	}

An example of my right click method (pseudo code)

public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {
//if I use server player and I update my GUI with my packet everything works beautifully
if (!world.isRemote){
PlayerParty pp = PlayerParty.get(player);
pp.swapPartyMembers(firstSelectedSlot, secondSelectedSlot);	
}
//However I am unsure how to update from client to server (i get a crash) if I call the swapPartyMembers method as it is up top and the consol points to a problem with my packet
if (world.isRemote){
PlayerParty pp = PlayerParty.get(Minecraft.GetMinecraft.thePlayer);
pp.swapPartyMembers(firstSelectedSlot, secondSelectedSlot);	
}
}

My SyncPlayerParty PacketClass

public class PacketSyncPlayerParty extends AbstractClientMessage<PacketSyncPlayerParty>
{

	private NBTTagCompound data;

	public PacketSyncPlayerParty() {}

	public PacketSyncPlayerParty(EntityPlayer player) {
		System.out.println("Updating Player Party Sending a Packet");
		data = new NBTTagCompound();
		PlayerParty.get(player).saveNBTData(data);
	}

	@Override
	protected void read(PacketBuffer buffer) throws IOException {
		data = buffer.readNBTTagCompoundFromBuffer();
	}

	@Override
	protected void write(PacketBuffer buffer) throws IOException {
		buffer.writeNBTTagCompoundToBuffer(data);
	}

	@Override
	public void process(EntityPlayer player, Side side) {
	PlayerParty.get(player).loadNBTData(data);
	}
}

 

For updating client player I use the following method in my PacketOverlord class I am not sure how to do the reverse of this

/**
 * Sends message to the specified player's client-side counterpart. See
 * {@link SimpleNetworkWrapper#sendTo(IMessage, EntityPlayerMP)}
 */
public static final void sendTo(IMessage message, EntityPlayerMP player) {
	PacketOverlord.dispatcher.sendTo(message, player);
}

 

 

 

Link to comment
Share on other sites

Generally, you NEVER update the server from the client.

 

What the client does instead is say, 'Hey, server, I want to do X' (i.e. send a packet to the server requesting some action) and the server then decides a) if that is allowed, and b) what the result is; once that is all done, if the client needs to know about the result then the server sends the result of the action back to the client (i.e. another packet).

 

So if, in your GUI, you have a button that swaps party members, instead of having the client swap the party members, you tell the server that the client player pressed the 'swap party' button, then the server decides what happens from there.

 

If whatever you are doing isn't very sensitive and you'd like to preview in the GUI (you can't wait more than a few milliseconds to see the results - this can be true when dealing with rendering), you can always swap the members on the client, too, in expectation of a successful transaction to the server, as long as the client data is overwritten by the results from the server.

Link to comment
Share on other sites

Ah ok I assume that is for security purposes, Another question, how would I send the request you mentioned? And I am not sure how to do the deciding bit on the server as I would have to do the deciding bit inside my IEEP class and am not sure how to access the server side player there.

Link to comment
Share on other sites

The player whose client sends the packet can be obtained from the message context passed with the message.

 

In terms of server "deciding" you just have to pass enough information or instruction in the packet payload. Like I have a GUI that gives an item when closed, so when the Done button is clicked in the GUI I send a packet with a special ID number (just the first int I put into the payload) and then when the server receives the packet it acts on that ID. So the client is telling the server what to do.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Ah ok I assume that is for security purposes, Another question, how would I send the request you mentioned? And I am not sure how to do the deciding bit on the server as I would have to do the deciding bit inside my IEEP class and am not sure how to access the server side player there.

... what? The 'request' is simply a packet, and whenever you process a packet you always have access to a player instance.

 

I understand it can seem daunting, but packets are really really simple: create the packet on one side (by create I mean you store some data in the packet class), send it over the network, and then read the same data back and do whatever you need to do with it. There is nothing magical going on.

Link to comment
Share on other sites

Once you figure out custom packets, like CoolAlias says it is actually pretty easy. Getting a solid packet handling system is a major step to becoming a serious modder, as there are many occasions where you will need it. So invest the time and figure it out.

 

diesieben07 has the basic packet setup using the simple network wrapper tutorial here: http://www.minecraftforge.net/forum/index.php/topic,20135.0.html

 

CoolAlias has a more comprehensive (but bit more complicated) system that overcomes a few of the limitations of the simple network wrapper here: http://www.minecraftforum.net/forums/mapping-and-modding/mapping-and-modding-tutorials/2137055-1-7-2-customizing-packet-handling-with

 

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Ok so I have the following

 

public class PacketSyncSwapPartyMembers extends AbstractClientMessage<PacketSyncSwapPartyMembers> {
int slot1;
int slot2;
boolean wasPressed;
public PacketSyncSwapPartyMembers() {}
public PacketSyncSwapPartyMembers(int slot1, int slot2, boolean wasPressed) {
	this.slot1 = slot1;
	this.slot2 = slot2;
	this.wasPressed =wasPressed;
}

@Override
protected void read(PacketBuffer buffer) throws IOException {
slot1 = buffer.readInt();
slot2 = buffer.readInt();
wasPressed = buffer.readBoolean();
}

@Override
protected void write(PacketBuffer buffer) throws IOException {
	buffer.writeInt(slot1);
	buffer.writeInt(slot2);
	buffer.writeBoolean(wasPressed);
}

@Override
public void process(EntityPlayer player, Side side) {
if(wasPressed == true && !player.worldObj.isRemote){
	 if(slot1 != -1 && slot2 !=-1){
		 PlayerParty ppp = PlayerParty.get(player);
		 ppp.swapPartyMembers(slot1, slot2, wasPressed);
		 PacketOverlord.sendTo(new PacketSyncPlayerParty((EntityPlayer) entityPlayer),(EntityPlayerMP) entityPlayer);
	 }
}
}}

 

and

inside my GUI I have this code but the server doesnt seem to update the client, my process method doesnt get called not sure why (I have very little experience with packets)

else if(button.id == BUTTON_SWITCH_ID){
    			
    			if(switchBtnPressed == true && firstSelectedSlot != -1 && secondSelectedSlot !=-1){
    			this.switchSuccessful = true;
    			ppp.swapPartyMembers(firstSelectedSlot, secondSelectedSlot,this.switchSuccessful);	
    			
                                PacketOverlord.sendToServer(new PacketSyncSwapPartyMembers(firstSelectedSlot, secondSelectedSlot, switchSuccessful));
    			this.mc.displayGuiScreen((GuiScreen)null);
    			this.mc.displayGuiScreen(battleMenuGuiPP);
    			firstSelectedSlot = -1;	
    			secondSelectedSlot = -1;
    			switchBtnPressed = false;
    			this.switchSuccessful = false;
    			
    			} else if(switchBtnPressed == true && firstSelectedSlot == -1 && secondSelectedSlot ==-1){
	    		         }else if(switchBtnPressed == true && firstSelectedSlot != -1 && secondSelectedSlot ==-1){
    				    	}else{
    				switchBtnPressed = true;
    			}
    			pwButton.wasBtnPressed = switchBtnPressed;
    			
    			}

Link to comment
Share on other sites

I did a System.out.println( "was pressed? " + wasPressed + "slot? " + slot1 + "slot? " + slot2); inside my constructor and all data appears to equal what it should but the process method isnt called at all

 

in my packet overlord class I use this to send the packet containing my request that says this button was pressed and these were the results take those results. Then I try to validate on server and nothing

/**
 * Send this message to the server. See
 * {@link SimpleNetworkWrapper#sendToServer(IMessage)}
 */
public static final void sendToServer(IMessage message) {
	PacketOverlord.dispatcher.sendToServer(message);
}

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.