Jump to content

[1.10] Packet/Capability Issues (SOLVED)


tripl3dogdare

Recommended Posts

So basically the gist of what I'm trying to do is send a packet from the server to the client to update a couple of simple Capability properties on a specific player. However, the client is not being updated, and it's values are locked at 0. The capability itself seems to work fine, and the packet is being both sent and received...

 

Relevant event handler code:

 

@SubscribeEvent public void onLivingUpdate(LivingUpdateEvent e) {
if(e.getEntity() instanceof EntityPlayer) {
	EntityPlayer player = (EntityPlayer)e.getEntity();
	checkBuffPairEquipped(player);
	updatePlayerMana(player);
}
}

private void updatePlayerMana(EntityPlayer player) {
IManaHandler mh = player.getCapability(ManaHandler.CAP, null);

mh.regenMana(5);
mh.updateClient(player);

System.out.println(mh.getMana()+","+mh.getMaxMana());
}

 

 

Mana handler "updateClient" method:

 

public void updateClient(EntityPlayer player) {
if(!player.getEntityWorld().isRemote && (mana != lastMana || maxMana != lastMaxMana))
	ChuuniMod.network.sendTo(new MessageUpdateClientMana(this), (EntityPlayerMP)player);

lastMana = mana;
lastMaxMana = maxMana;
}

 

 

Packet class:

 

public class MessageUpdateClientMana implements IMessage {

private int mana, maxMana;

public MessageUpdateClientMana() {}
public MessageUpdateClientMana(IManaHandler mh) {
	this.mana = mh.getMana();
	this.maxMana = mh.getMaxMana();
}

public void fromBytes(ByteBuf buf) {
	mana = ByteBufUtils.readVarInt(buf, 4);
	maxMana = ByteBufUtils.readVarInt(buf, 4);
}

public void toBytes(ByteBuf buf) {
	buf.writeInt(mana);
	buf.writeInt(maxMana);
}

public static class Handler implements IMessageHandler<MessageUpdateClientMana, IMessage> {
	public IMessage onMessage(MessageUpdateClientMana message, MessageContext ctx) {
		Minecraft.getMinecraft().addScheduledTask(() -> {
			EntityPlayer player = Minecraft.getMinecraft().thePlayer;
			IManaHandler mh = player.getCapability(ManaHandler.CAP, null);

			mh.setMana(message.mana);
			mh.setMaxMana(message.maxMana);

			System.out.println("packet recieved!");
		});
		return null;
	}
}

}

 

 

Long story short, if the player's mana has changed since the last tick I send a packet from the server to the client that should update their client-side mana values, but despite the packet being sent and received properly their mana doesn't update. Any ideas? I'm stumped.

 

Edit: Ok, I'm officially stupid... I changed from the ByteBufUtils read methods to the builtin ones and it worked -_-

Link to comment
Share on other sites

I'd just like to add:

* For players use PlayerTickEvent (tick events have phases meaning pick START or END).

* Redesign your stuff:

- You don't need prev/next (or last/current whatever you call it) variables.

- Make setter method that will (if called on server) send packet whenever "valueToSet != current".

- I'd also split "mana" and "maxMana" into separate packets (and apply tip above).

- You seem to not store EntityPlayer inside Capability (assuming that since you are passing EntityPlayer to #updateClient method) - you could redesign it without passing such args.

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

Thanks for the suggestions! I've been working on it a lot trying to iron out the kinks... and I've hit another block. Everything is now working fine - the client and server are in sync, everything seems to be working properly, except the data isn't saving into the world file.

 

Note: In working on the system, I ended up implementing some of your suggestions, namely using PlayerTickEvent and using a single "dirty" variable instead of the "last***" variables to determine whether an update is necessary.

 

Relevant event handlers:

 

@SubscribeEvent public void addPlayerCapabilities(AttachCapabilitiesEvent.Entity e) {
if(e.getEntity() instanceof EntityPlayer)
	e.addCapability(new ResourceLocation(ChuuniMod.MODID, "ManaHandler"), new ManaHandler());
}

@SubscribeEvent public void persistPlayerCapabilities(PlayerEvent.Clone e) {
if(e.isWasDeath()) {
	IManaHandler cnew = e.getEntityPlayer().getCapability(ManaHandler.CAP, null);
	IManaHandler cold = e.getOriginal().getCapability(ManaHandler.CAP, null);

	cold.copyTo(cnew);
}
}

@SubscribeEvent public void onPlayerTick(PlayerTickEvent e) {
if(e.phase != Phase.END) return;

checkBuffPairEquipped(e.player);
updatePlayerMana(e.player);
}

private void updatePlayerMana(EntityPlayer player) {
if(!player.worldObj.isRemote) {
	IManaHandler mh = player.getCapability(ManaHandler.CAP, null);

	mh.regenMana(mh.getManaRegen());
	mh.updateClient(player);
}
}

 

 

IManaHandler (includes all the capability/packet code):

 

public interface IManaHandler {

public float getMana();
public float getMaxMana();
public float getManaRegen();

public float setMana(float amount);
public float setMaxMana(float amount);
public float setManaRegen(float amount);

public boolean consumeMana(float amount);
public boolean regenMana(float amount);

public void copyTo(IManaHandler other);
public void updateClient(EntityPlayer player);

public static class ManaHandler implements IManaHandler, ICapabilitySerializable<NBTTagCompound> {

	@CapabilityInject(IManaHandler.class) public static final Capability<IManaHandler> CAP = null;
	private float mana,maxMana, manaRegen;
	private float lastMana, lastMaxMana, lastManaRegen;
	private boolean dirty = true;

	public ManaHandler() { this(0, 250, .25f); }
	public ManaHandler(float mana, float maxMana, float manaRegen) {
		this.mana = mana;
		this.maxMana = maxMana;
		this.manaRegen = manaRegen;
	}

	public float getMana() { return mana; }
	public float getMaxMana() { return maxMana; }
	public float getManaRegen() { return manaRegen; }

	public float setMana(float amount) { dirty = true; return mana = amount; }
	public float setMaxMana(float amount) { dirty = true; return maxMana = amount; }
	public float setManaRegen(float amount) { dirty = true; return manaRegen = amount; }

	public NBTTagCompound get() { return serializeNBT(); }
	public void set(NBTTagCompound nbt) { deserializeNBT(nbt); }

	public boolean consumeMana(float amount) {
		if(mana < amount) return false;
		setMana(mana-amount);
		return true;
	}

	public boolean regenMana(float amount) {
		if(mana == maxMana) return false;
		setMana(Math.min(mana+amount, maxMana));
		return true;
	}

	public void copyTo(IManaHandler other) {			
		other.setMaxMana(this.getMaxMana());
		other.setManaRegen(this.getManaRegen());
	}

	public boolean hasCapability(Capability<?> capability, EnumFacing facing) { return capability == CAP; }
	public <T> T getCapability(Capability<T> capability, EnumFacing facing) { return capability == CAP ? (T)this : null; }
	public static IManaHandler instanceFor(EntityPlayer player) { return player.getCapability(CAP, null); }

	public NBTTagCompound serializeNBT() {
		NBTTagCompound nbt = new NBTTagCompound();
		nbt.setFloat("mana", mana);
		nbt.setFloat("maxMana", maxMana);
		nbt.setFloat("manaRegen", manaRegen);
		return nbt;
	}

	public void deserializeNBT(NBTTagCompound nbt) {
		setMana(nbt.getFloat("mana"));
		setMaxMana(nbt.getFloat("maxMana"));
		setManaRegen(nbt.getFloat("manaRegen"));
	}

	public void updateClient(EntityPlayer player) {
		if(!player.getEntityWorld().isRemote) {
			if(dirty) CommonProxy.network.sendTo(new MessageUpdateClientMana(this), (EntityPlayerMP)player);
			dirty = false;
		}
	}

	public static class Storage implements IStorage<IManaHandler> {

		public NBTTagCompound writeNBT(Capability<IManaHandler> capability, IManaHandler instance, EnumFacing side) {
			return ((ManaHandler)instance).serializeNBT();
		}

		public void readNBT(Capability<IManaHandler> capability, IManaHandler instance, EnumFacing side, NBTBase nbt) {
			((ManaHandler)instance).deserializeNBT((NBTTagCompound)nbt);
		}

	}

}

/** Packet used to update client-side capabilities */
public static class MessageUpdateClientMana implements IMessage {

	private float mana, maxMana, manaRegen;

	public MessageUpdateClientMana() {}
	public MessageUpdateClientMana(IManaHandler mh) { 
		this.mana = mh.getMana();
		this.maxMana = mh.getMaxMana();
		this.manaRegen = mh.getManaRegen();
	}

	public void fromBytes(ByteBuf buf) {
		mana = buf.readFloat();
		maxMana = buf.readFloat();
		manaRegen = buf.readFloat();
	}

	public void toBytes(ByteBuf buf) {
		buf.writeFloat(mana);
		buf.writeFloat(maxMana);
		buf.writeFloat(manaRegen);
	}

	public static class Handler implements IMessageHandler<MessageUpdateClientMana, IMessage> {
		public IMessage onMessage(MessageUpdateClientMana message, MessageContext ctx) {
			Minecraft.getMinecraft().addScheduledTask(() -> {
				EntityPlayer player = Minecraft.getMinecraft().thePlayer;
				IManaHandler mh = ManaHandler.instanceFor(player);

				mh.setMana(message.mana);
				mh.setMaxMana(message.maxMana);
				mh.setManaRegen(message.manaRegen);
				System.out.println("Client: "+message.mana+","+message.maxMana+","+message.manaRegen);
			});
			return null;
		}
	}

}

}

 

 

CommonProxy (registers packet/capability among other things):

 

public class CommonProxy {

public static final SimpleNetworkWrapper network = NetworkRegistry.INSTANCE.newSimpleChannel(ChuuniMod.MODID);

public void init() {
	ChuuniConfig.initServer();
	ChuuniConfig.initCommon();

	CapabilityManager.INSTANCE.register(IManaHandler.class, new ManaHandler.Storage(), ManaHandler::new);
	MinecraftForge.EVENT_BUS.register(new ChuuniEventHandler());

	registerNetworkPackets();
}

private void registerNetworkPackets() {
	int id = 0;
	network.registerMessage(MessageUpdateClientMana.Handler.class, MessageUpdateClientMana.class, id++, Side.CLIENT);
}

}

 

 

I'm using NBTExplorer to directly track what data is saved, and while everything works fine ingame, the data only saves to the world file about 1/20ish times if that and I have no idea why.

 

Edit: Apparently NBTExplorer being open was screwing with it... FML.

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.