Jump to content

[1.10.2] Issue with Packets [SOLVED]


hugo_the_dwarf

Recommended Posts

I'm working with a system of:

Press Keybinding to open "Player Class Menu"

Select Class and/or Profession in GUI

Press save

Fire packet from client to server

check to see if player has a class, no class allow free class change. Else check to see if they have enough gold to change.

Send Response Packet to update client (server > client)

 

Where it apparently is failing is I'm guessing the saving portion within the "requestPacket"(client > server)

As the changes never stay, or save.

 

[spoiler=gui code]

package htd.rot.client.gui;

import org.lwjgl.opengl.GL11;

import htd.rot.Rot;
import htd.rot.capability.attribute.CapAttribute;
import htd.rot.capability.attribute.CapAttributeData;
import htd.rot.capability.playerextra.CapPlayerExtra;
import htd.rot.capability.playerextra.CapPlayerExtraData;
import htd.rot.comms.packets.ClassRequestPacket;
import htd.rot.comms.packets.ProfessionRequestPacket;
import htd.rot.managers.PacketManager;
import htd.rot.managers.PlayerCPTypeManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;

public class GuiClassSelection extends GuiContainer {
public static final ResourceLocation texture = new ResourceLocation(Rot.MODID.toLowerCase(),
		"textures/gui/rotGui.png");

private EntityPlayer player;
private int pad = 4;
private int ch = 20;
private int selectedClass = -1;
private int selectedProfession = -1;

public GuiClassSelection(EntityPlayer player)
{
	super(new ContainerNull());

	this.player = player;
	this.xSize = 176;
	this.ySize = 166;
	this.selectedClass = player.getCapability(CapPlayerExtra.CAPABILITY, null).currentClass;
	this.selectedProfession = player.getCapability(CapPlayerExtra.CAPABILITY, null).currentProfession;
}

/** Button Clicks **/
@Override
protected void actionPerformed(GuiButton button)
{
	switch (button.id)
	{
	case 0: // Class Forward
		this.selectedClass++;
		this.selectedClass = this.selectedClass == PlayerCPTypeManager.classes.length ? 0 : this.selectedClass;
		break;
	case 1: // Class Back
		this.selectedClass--;
		this.selectedClass = this.selectedClass < 0 ? PlayerCPTypeManager.classes.length - 1 : this.selectedClass;
		break;
	case 2: // Change Class
		PacketManager.INSTANCE.sendToServer(new ClassRequestPacket(selectedClass));
		break;
	case 3: // Refresh Class
		PacketManager.INSTANCE.sendToServer(new ClassRequestPacket(0));
		break;
	case 4: // Profession Forward
		this.selectedProfession++;
		this.selectedProfession = this.selectedProfession == PlayerCPTypeManager.professions.length ? 0
				: this.selectedProfession;
		break;
	case 5: // Profession Back
		this.selectedProfession--;
		this.selectedProfession = this.selectedProfession < 0 ? PlayerCPTypeManager.professions.length - 1
				: this.selectedProfession;
		break;
	case 6: // Change Profession
		PacketManager.INSTANCE.sendToServer(new ProfessionRequestPacket(selectedProfession));
		break;
	case 7:// Refresh Profession
		PacketManager.INSTANCE.sendToServer(new ProfessionRequestPacket(0));
		break;
	}
}

@Override
protected void drawGuiContainerBackgroundLayer(float f, int i, int j)
{

	/*
	 * TextureManager manager = Minecraft.getMinecraft().renderEngine;
	 * manager.bindTexture(manager.getResourceLocation(1)); //RENDER ITEMS
	 * drawTexturedModelRectFromIcon(300, 300,
	 * RotItems.itemGunpowderInfuser.getIconFromDamage(0), 16, 16);
	 */

	GL11.glColor4f(1F, 1F, 1F, 1F);
	Minecraft.getMinecraft().renderEngine.bindTexture(texture);
	drawTexturedModalRect(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize);

	this.buttonList.clear();
	// Start with main control buttons

	CapPlayerExtraData playerExtra = player.getCapability(CapPlayerExtra.CAPABILITY, null);
	CapAttributeData attrs = player.getCapability(CapAttribute.CAPABILITY, null);

	int x1 = this.guiLeft + this.pad;
	int x2 = (this.guiLeft + this.xSize) - (8 + this.pad);
	int x3 = (x2 + x1) / 2;

	int textY = this.guiTop + this.pad;
	int textX = (this.guiLeft + this.xSize) + pad;

	this.buttonList.add(new GuiClassSelectionButton(0, x2, this.guiTop + this.pad, "", 1));
	this.buttonList.add(new GuiClassSelectionButton(4, x2, this.guiTop + this.pad + (8 * 2), "", 1));

	this.drawString(this.fontRendererObj, this.selectedClass != -1 ? PlayerCPTypeManager.classes[this.selectedClass].className : "None", x3,
			this.guiTop + this.pad + 5, 0xddeeee);

	this.drawString(this.fontRendererObj, this.selectedProfession != -1 ? PlayerCPTypeManager.professions[this.selectedProfession].professionName : "None",
			x3, this.guiTop + this.pad + 20, 0xddeeee);

	this.buttonList.add(new GuiClassSelectionButton(1, x2 - 8, this.guiTop + this.pad, "", 0));
	this.buttonList.add(new GuiClassSelectionButton(2, x2 - 8, this.guiTop + this.pad + 8, "", 2));
	this.buttonList.add(new GuiClassSelectionButton(3, x2, this.guiTop + this.pad + 8, "", 3));

	this.buttonList.add(new GuiClassSelectionButton(5, x2 - 8, this.guiTop + this.pad + (8 * 2), "", 0));
	this.buttonList.add(new GuiClassSelectionButton(6, x2 - 8, this.guiTop + this.pad + (8 * 3), "", 2));
	this.buttonList.add(new GuiClassSelectionButton(7, x2, this.guiTop + this.pad + (8 * 3), "", 3));

	this.drawString(this.fontRendererObj, "Current Class:", textX, textY, 0xdbdd15);
	textY += 15;
	this.drawString(this.fontRendererObj, playerExtra.currentClass == -1 ? "None" : PlayerCPTypeManager.classes[playerExtra.currentClass].className, textX, textY,
			0xdbdd15);
	textY += 15;
	for (int index = 0; index < attrs.attributes.length;index++)
	{
		this.drawString(this.fontRendererObj, attrs.ATTRIBUTE_TAGS[index] + ": " + attrs.attributes[index], textX, textY,
				attrs.attributes[index] == 0 ? 0xFFFFFF
						: attrs.attributes[index] > 0 ? 0x00ff42 : 0xff0c00);
		textY += 15;
	}
	this.drawString(this.fontRendererObj, "Current Profession:", textX, textY, 0xdbdd15);
	textY += 15;
	this.drawString(this.fontRendererObj, playerExtra.currentProfession == -1 ? "None" : PlayerCPTypeManager.professions[playerExtra.currentClass].professionName, textX, textY,
			0xdbdd15);

	// Visual information on location
	/*
	 * this.drawString(fontRendererObj, "X: "+(xOffset+te.xCoord)+
	 * " offSet: "+xOffset, (startLeft + ((gridSizeX * 2) * cw)) + cw * 5,
	 * (startTop + (gridSizeZ * ch) + 4) - ch, 0xFFFFFF);
	 * this.drawString(fontRendererObj, "Y: "+(yOffset+te.yCoord)+
	 * " offSet: "+yOffset, (startLeft + ((gridSizeX * 2) * cw)) + cw * 5,
	 * (startTop + (gridSizeZ * ch) + 4), 0xFFFFFF);
	 * this.drawString(fontRendererObj, "Z: "+(zOffset+te.zCoord)+
	 * " offSet: "+zOffset, (startLeft + ((gridSizeX * 2) * cw)) + cw * 5,
	 * (startTop + (gridSizeZ * ch) + 4) + ch, 0xFFFFFF);
	 */
}

/** Keyboard Clicks **/
@Override
protected void keyTyped(char par1, int par2)
{
	if ((par2 == 1) || (par2 == this.mc.gameSettings.keyBindInventory.getKeyCode()))
	{
		this.mc.thePlayer.closeScreen();
	}
}
}

 

 

[spoiler=request packet]

package htd.rot.comms.packets;

import htd.rot.capability.playerextra.CapPlayerExtra;
import htd.rot.capability.playerextra.CapPlayerExtraData;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;

public class ClassRequestPacket implements IMessage {

public static class ClassRequestPacketHandler implements IMessageHandler<ClassRequestPacket, IMessage> {

	@Override
	public IMessage onMessage(ClassRequestPacket message, MessageContext ctx)
	{
		final int goldCost = 500;

		if (message.classID == -1)
		{
			return null;
		}

		EntityPlayer player = ctx.getServerHandler().playerEntity;
		CapPlayerExtraData props = player.getCapability(CapPlayerExtra.CAPABILITY, null);
		if (props.currentClass == -1)
		{
			props.currentClass = message.classID;
			return new ClassResponsePacket(props.currentClass,props.gold);
		} else
		{
			if (props.playerInfo[props.gold] >= goldCost)
			{
				props.playerInfo[props.gold] -= goldCost;
				props.currentClass = message.classID;
				return new ClassResponsePacket(props.currentClass,props.gold);
			}
		}			
		return null;
	}

}

public int classID;

public ClassRequestPacket()
{

}

public ClassRequestPacket(int className)
{
	this.classID = className;
}

@Override
public void fromBytes(ByteBuf buf)
{
	this.classID = buf.readInt();
}

@Override
public void toBytes(ByteBuf buf)
{
	buf.writeInt(this.classID);
}

}

 

 

[spoiler=response packet]

package htd.rot.comms.packets;

import htd.rot.capability.playerextra.CapPlayerExtra;
import htd.rot.capability.playerextra.CapPlayerExtraData;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;

public class ClassResponsePacket implements IMessage {

public static class ClassResponsePacketHandler implements IMessageHandler<ClassResponsePacket, IMessage> {

	@Override
	public IMessage onMessage(ClassResponsePacket message, MessageContext ctx)
	{
		EntityPlayer player = Minecraft.getMinecraft().thePlayer;
		player.getCapability(CapPlayerExtra.CAPABILITY, null).currentClass = message.classID;
		player.getCapability(CapPlayerExtra.CAPABILITY, null).playerInfo[CapPlayerExtraData.gold] = message.gold;
		return null;
	}

}

public int classID, gold;

public ClassResponsePacket()
{

}

public ClassResponsePacket(int className, int gold)
{
	this.classID = className;
	this.gold = gold;
}

@Override
public void fromBytes(ByteBuf buf)
{
	this.classID = buf.readInt();
	this.gold = buf.readInt();
}

@Override
public void toBytes(ByteBuf buf)
{
	buf.writeInt(this.classID);
	buf.writeInt(this.gold);
}

}

 

 

I'm pulling most of my code from the old 1.8.2 era and trying to touch it up. And this is more or less the same format

 

Oh the packet registery (for the sides, hopefully I have them correct, I do get some action if I use a Console.Out in the request so it's at least going somewhere)

 

		INSTANCE.registerMessage(CapAttributePacketHandler.class, CapAttributePacket.class, packetId++, Side.CLIENT);
	INSTANCE.registerMessage(CapPlayerExtraPacketHandler.class, CapPlayerExtraPacket.class, packetId++,
			Side.CLIENT);
	INSTANCE.registerMessage(CapPlayerUpdateRequestPacketHandler.class, CapPlayerUpdateRequestPacket.class,
			packetId++, Side.SERVER);
	INSTANCE.registerMessage(ClassGUIPacketHandler.class, ClassGUIPacket.class, packetId++, Side.SERVER);
	INSTANCE.registerMessage(ClassRequestPacketHandler.class, ClassRequestPacket.class, packetId++, Side.SERVER);
	INSTANCE.registerMessage(ClassResponsePacketHandler.class, ClassResponsePacket.class, packetId++, Side.CLIENT);
	INSTANCE.registerMessage(ProfessionRequestPacketHandler.class, ProfessionRequestPacket.class, packetId++,
			Side.SERVER);
	INSTANCE.registerMessage(ProfessionResponsePacketHandler.class, ProfessionResponsePacket.class, packetId++,
			Side.CLIENT);

Link to comment
Share on other sites

Packet handlers are run on a separate thread, you must schedule a task to run on the main thread before you can safely interact with normal Minecraft classes. Forge's documentation explains this here.

 

Apart from that, your code looks like it should work. Could you post the

ICapabilityProvider

you attach to players to provide your capability?

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

[spoiler=CapPlayerExtraProvider]

package htd.rot.capability.playerextra;

import htd.rot.Rot;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;

public class CapPlayerExtraProvider implements ICapabilityProvider, ICapabilitySerializable<NBTTagCompound> 
{

public static final ResourceLocation KEY = new ResourceLocation(Rot.MODID, "htd_playerextra");

private CapPlayerExtraData INSTANCE = new CapPlayerExtraData();

public CapPlayerExtraProvider(EntityLivingBase entity)
{
	INSTANCE.setEntity(entity);
}

@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing)
{
	return capability == CapPlayerExtra.CAPABILITY;
}

@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing)
{
	if (capability == CapPlayerExtra.CAPABILITY)return (T)INSTANCE;
	return null;
}

@Override
public NBTTagCompound serializeNBT()
{
	return (NBTTagCompound)CapPlayerExtra.CAPABILITY.writeNBT(INSTANCE, null);
}

@Override
public void deserializeNBT(NBTTagCompound nbt)
{
	CapPlayerExtra.CAPABILITY.readNBT(INSTANCE, null, nbt);
}

}

 

 

I know strangely if I have the Capability randomly assign values to values, and have a full data sync (so server and client are out of sync with different Random.nextInt() values) the client will be updated through the code in the playerTick and livingUpdate events with a simple just fire it off from the server to client (dataChanged() method).

 

So would I have to rewrite some of my packet handlers to appear like this?

 

		@Override
	public IMessage onMessage(ClassGUIPacket message, MessageContext ctx)
	{
		// Open the gui on the server so we can actually do stuff.
		EntityPlayer player = ctx.getServerHandler().playerEntity;
		ctx.getServerHandler().
			playerEntity.
				getServerWorld().
					addScheduledTask(
							new Runnable() {
								public void run()
								{
									player.openGui(Rot.INSTANCE, GuiHandler.CLASS_GUI, player.worldObj, 
											(int) player.posX, 
											(int) player.posY,
											(int) player.posZ);
								}
							});			
		return null;
	}
}

 

Of course if I have a request/repsonse system would I add inside the runnable (task) a "PacketManager.INSTANCE.SendTo()" and just leave my returns as NULL?

Link to comment
Share on other sites

OMG I'm just an idiot

Was switching from an old way how I did things to a new way that I figure would be "easier" to manage the reading/writing of packet buffers and NBT

 

Where I have 3 vars 2 of them are arrays

One set to be a named Index

One Array for Name/Keys

Final Array for stored Data

 

So in the given packet classes

 

I have "props.currentClass" which is my index...

It should have been "props.playerInfo[props.currentClass]"

 

So now i'm changing the indexes to FINAL and making them all CAPS, and will be creating some getter/setter methods

 

EDIT:

 

Thanks for the help, but I still have the question of the

New Runable(SendTo(message,player)) for my request packets to send the response. or any packet for that matter.

Link to comment
Share on other sites

Yes, the return value of

IMessageHandler#onMessage

isn't that useful these days, since you need to do the actual processing asynchronously on the main thread. Just send the response message manually with your

SimpleNetworkWrapper

instance.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

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.