Jump to content

[1.12.2] Best way to handle capability data syncing?


Alekseyev

Recommended Posts

Hey there,

 

I have a capability with a boolean (active status) and an integer value (a charge value).

 

I want to check this data for many effects and events.

 

Here are my current cases: BreakSpeed and Jump Height (but planning to add more later on, such as attack damage or mob behaviour)

I want to make it so that when the boolean is active, the player's block breaking speed is doubled or jump height increased. This works fine. However, I also want to reduce the charge value while doing this. When simply using the code further down, a desync in the values known by the client and by the server starts to manifest after prolonged usage, from both the block breaking and jump height. The debug chat line also appears twice per side for some reason, with the second time showing the already incremented charge value.

 

This makes me wonder: What is the best way to handle capability data like this? Since some data is handled by the server and other data by the client (such as movement), the data would have to be present on both, but considering that the charge is modified so highly frequently, sending a packet every frame surely can't be the right way to handle it?

 

	@SubscribeEvent
	public void breakingSpeed(net.minecraftforge.event.entity.player.PlayerEvent.BreakSpeed event)
	{
		if (getBioData(player).getMaskActive())
		{
			Item mask = player.inventory.armorItemInSlot(3).getItem();

			if (mask == ItemInit.KANOHI_PAKARI)
			{
				event.setNewSpeed(event.getNewSpeed() * 2);
				getBioData(player).modifyMaskCharge(-5);
				if (player.ticksExisted % 20 == 0)
				{
					player.sendStatusMessage(new TextComponentString(TextFormatting.DARK_GRAY + "Speeds: New: " + event.getNewSpeed() + " Old: " + event.getOriginalSpeed()), false);
				}
			}
		}
	}

 

	@SubscribeEvent
	public void jumpEffect(LivingEvent.LivingJumpEvent event)
	{
		if (event.getEntity() instanceof EntityPlayer)
		{
			EntityPlayer evPlayer = (EntityPlayer)event.getEntity();

			if (getBioData(evPlayer).getMaskActive() && evPlayer.inventory.armorItemInSlot(3).getItem() == ItemInit.KANOHI_MIRU && getBioData(evPlayer).getMaskCharge() >= 1000)
			{
				evPlayer.motionY += 0.7D;
				evPlayer.motionX *= 4.0D;
				evPlayer.motionZ *= 4.0D;
				getBioData(evPlayer).modifyMaskCharge(-1000);
			}
		}
	}

 

	@SubscribeEvent
	public void playerTick(TickEvent.PlayerTickEvent event)
	{
		if (!(player.inventory.armorItemInSlot(3).getItem() instanceof Kanohi) && getBioData(player).getMaskActive() == true)
		{
			getBioData(player).setMaskActive(false);
			player.sendStatusMessage(new TextComponentString(TextFormatting.RED + event.side.name() + " Mask unequipped, setting to: " + (getBioData(player).getMaskActive() ? "On" : "Off")), false);
		}

		if (getBioData(player).getMaskActive())
		{
			Item mask = player.inventory.armorItemInSlot(3).getItem();

			if (mask == ItemInit.KANOHI_MIRU)
			{
				player.fallDistance = 0;
			}
		}
		else
		{
			getBioData(player).modifyMaskCharge(+10);  //Increasing charge with mask deactivated
		}

		if (player.ticksExisted % 100 == 0)
		{
			player.sendStatusMessage(new TextComponentString(TextFormatting.DARK_RED + event.side.name() + " Mask: " + (getBioData(player).getMaskActive() ? "On" : "Off")  + " Charge: " + getBioData(player).getMaskCharge()), false);
		}
	}

 

public class DefaultBioPlayerDataHandler implements IBioPlayerDataHandler
{
    private BioElements element;
    private Boolean maskActive = false;
    private int maskCharge = 10000;
    private final int maxCharge = 10000;

    @Override
    public BioElements getElement() {
        return element;
    }

    @Override
    public void setElement(BioElements element) {
        this.element = element;
    }

    @Override
    public void removeElement() {
        this.element = BioElements.NONE;
    }

	@Override
    public Boolean getMaskActive()
	{
		return maskActive;
	}

	@Override
	public void setMaskActive(Boolean status)
	{
		this.maskActive = status;
	}

	@Override
	public int getMaskCharge()
	{
		return this.maskCharge;
	}

	@Override
	public void setMaskCharge(int charge)
	{
		this.maskCharge = charge;
	}

	@Override
	public void modifyMaskCharge(int modifier)
	{
		if (maskCharge + modifier >= 0)
		{
			if (maskCharge + modifier <= maxCharge)
			{
				maskCharge = maskCharge + modifier;
			}
			else
			{
				maskCharge = maxCharge;
			}
		}
		else
		{
			maskCharge = 0;
			maskActive = false;
		}
	}
}

 

Edited by Alekseyev
Link to comment
Share on other sites

I thought about the following: Instead of checking the charge value and being updated on it, the client just has a boolean for "1000 or higher". The server then only sends an update packet whenever the charge value crosses this treshold.
However, there is a problem: I also want the charge to be displayed on the HUD later (in the form of a bar of varying size), and to calculate that size, you'd need the value 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.

×
×
  • Create New...

Important Information

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