Jump to content

[1.12.2] [SOLVED] Syncing player capability to client


bmwalter68

Recommended Posts

Hi all!  I have a question about player capabilities in 1.12.2...  I'm trying to use a player capability to store the last time one of my items was used by the player to effect a cooldown period that is tied to the player, not the itemstack.  Basically, "You are only allowed to use any instance of this item every X minutes."  The functionality is working as expected, the problem I'm having is keeping the last used time in sync with the client for display purposes.  I've built a custom sync packet to update the last used value on the client, and I send the packet during PlayerLoggedInEvent, PlayerChangedDimensionEvent and PlayerEvent.Clone when isWasDeath() is true.  The sync packet is also working as expected, arriving and updating the client.  The problem I'm encountering looks to be related to the order that events fire surrounding player death.

 

Here is the result of some logging:

 

[10:34:01] [Server thread/INFO]: bmwalter68 fell from a high place
[10:34:01] [main/INFO]: [CHAT] bmwalter68 fell from a high place
[10:34:02] [Server thread/INFO] [transporterng]: [SERVER] new EvacuationCooldown(EntityPlayer)
[10:34:02] [Server thread/INFO] [transporterng]: [SERVER] onAttachCapabilities
[10:34:02] [Server thread/INFO] [transporterng]: [SERVER] onPlayerClone: oldCooldown=EvacuationCooldown{lastUse=1518536021113, player=EntityPlayerMP['bmwalter68'/139, l='Overworld', x=-237.43, y=63.00, z=-206.25]} newCooldown=EvacuationCooldown{lastUse=0, player=EntityPlayerMP['bmwalter68'/1268, l='Overworld', x=-221.50, y=64.00, z=-86.50]}
[10:34:02] [Server thread/INFO] [transporterng]: [SERVER] EvacuationCooldown:setLastUse(1518536021113) player=EntityPlayerMP['bmwalter68'/1268, l='Overworld', x=-221.50, y=64.00, z=-86.50]
[10:34:02] [Server thread/INFO] [transporterng]: [SERVER] EvacuationCooldown:updateClient(1518536021113) player=EntityPlayerMP['bmwalter68'/1268, l='Overworld', x=-221.50, y=64.00, z=-86.50]
[10:34:02] [Server thread/INFO] [transporterng]: [SERVER] onPlayerClone: client updated
[10:34:02] [main/INFO] [transporterng]: [CLIENT] EvacuationCooldown:setLastUse(1518536021113) player=EntityPlayerSP['bmwalter68'/139, l='MpServer', x=-237.43, y=63.00, z=-206.25]
[10:34:02] [main/INFO] [transporterng]: [CLIENT] new EvacuationCooldown(EntityPlayer)
[10:34:02] [main/INFO] [transporterng]: [CLIENT] onAttachCapabilities

 

The event handler code for PlayerEvent.Clone:

 

		@SubscribeEvent
		public static void onPlayerCloneEvent(PlayerEvent.Clone event) {
			if (!event.isWasDeath()) {
				return;
			}

			IEvacuationCooldown oldCooldown = event.getOriginal().getCapability(EVACUATION_COOLDOWN, null);
			IEvacuationCooldown newCooldown = event.getEntityPlayer().getCapability(EVACUATION_COOLDOWN, null);

			if (oldCooldown != null && newCooldown != null) {
				newCooldown.setLastUse(oldCooldown.getLastUse());
				newCooldown.updateClient();
			}
		}

 

It looks like the client gets updated properly and then a new capability instance is attached, effectively replacing the value just updated via the packet.  Am I missing something obvious here, or is this just simply a timing issue I need to account for?

Edited by bmwalter68
Mark as solved
Link to comment
Share on other sites

Following up my own post...  I have this working, though I'm not sure I'm in love with the solution.  Instead of pushing updates from server to client in PlayerChangedDimensionEvent  and PlayerEvent.Clone, I added another CLIENT => SERVER packet which requests a capability update and added it to the AttachCapabilitiesEvent on the client side:

 

		@SubscribeEvent
		public static void onAttachCapabilitiesEvent(AttachCapabilitiesEvent<Entity> event) {
			if (event.getObject() instanceof EntityPlayer) {
				EntityPlayer player = (EntityPlayer)event.getObject();
				event.addCapability(new ResourceLocation(Reference.MODID, "evacuation_cooldown"), new Provider(new EvacuationCooldown(player)));
				if (player.getEntityWorld().isRemote) {
					PacketHandler.instance.sendToServer(new RequestEvacuateCooldownUpdateMessage());
				}
			}
		}

 

This handles both the player changing dimensions and updating the client after death.  PlayerEvent.Clone still needs to handle copying the data on the server side, but doesn't update the client:

 

		@SubscribeEvent
		public static void onPlayerCloneEvent(PlayerEvent.Clone event) {
			if (!event.isWasDeath()) {
				return;
			}

			IEvacuationCooldown oldCooldown = event.getOriginal().getCapability(EVACUATION_COOLDOWN, null);
			IEvacuationCooldown newCooldown = event.getEntityPlayer().getCapability(EVACUATION_COOLDOWN, null);

			if (oldCooldown != null && newCooldown != null) {
				newCooldown.setLastUse(oldCooldown.getLastUse());
			}
		}

 

This currently works, but for some reason this seems like too many hoops to be jumping through.  Does anyone have a better solution?

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.



×
×
  • Create New...

Important Information

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