Class EntityStatMap

java.lang.Object
com.hypixel.hytale.server.core.modules.entitystats.EntityStatMap
All Implemented Interfaces:
Component<EntityStore>, Cloneable

public class EntityStatMap extends Object implements Component<EntityStore>
Entity Stat Value map

Systems that wish to modify stat values should implement the system type interface EntityStatsSystems.StatModifyingSystem. Otherwise changes made to stats may not trigger interactions correctly.

Prediction implementation

Changes to entity stats can, in some cases, be predicted by the client. This is done in order to reduce the feel of latency for players. The predictability of stat changes can controlled via EntityStatMap.Predictable which is an optional parameter to most stat changing methods.

Prediction for entity stats introduces some challenges due to the way they work and the way they can be used. For starters the client cannot predict everything, a stat can have changes that are both predictable and non-predictable. Even predictable changes may not be predictable to other clients and can only be predicted by the one of the clients.

The next challenge is caused by the fact that the order of operations is important with stats and given that the client doesn't know every operation that is being performed on a stat it will perform things in the wrong order or have gaps in the operations it performs. For example:

  1. Initial state: value=5, min=0, max=10
  2. Server only: op=Clear, newValue=0
  3. Predictable: op=Add, amount=6, newValue=6

In the above example the server performs all the actions and gets the result 6. Given that the Clear operation was called only on the server however its possible due to lag that the client will predict the Add call first before seeing the Clear. If the client just executed this in the order it saw them then it would get the result 0 (Or if Clear was implemented as a subtraction -5, it would still have the wrong result of 5 due to the fact the Add operation would saturate the stat at 10).

In order to keep the order the client needs to keep track of the server's state of any entity stat and a list of predictions it has made. Whenever it gets an update from the server it'll first apply the change to the server copy of the stats. Then it'll check if it predicted the change, if it did it'll delete the prediction entry and stop looking for it. Afterwards it will apply the change to predicted copy of the stats by copying the server's state and then re-applying all pending prediction it has made. If the server value is marked as predictable but wasn't predicted then we store it to catch the client predicting later than the server (should be rare however).

One limitation of the system is that the changes must match exactly.

  • Field Details

    • VERSION

      public static final int VERSION
      See Also:
    • CODEC

      public static final BuilderCodec<EntityStatMap> CODEC
    • selfUpdates

      @Nonnull public final it.unimi.dsi.fastutil.ints.Int2ObjectMap<List<EntityStatUpdate>> selfUpdates
    • selfStatValues

      @Nonnull public final it.unimi.dsi.fastutil.ints.Int2ObjectMap<it.unimi.dsi.fastutil.floats.FloatList> selfStatValues
    • otherUpdates

      @Nonnull public final it.unimi.dsi.fastutil.ints.Int2ObjectMap<List<EntityStatUpdate>> otherUpdates
  • Constructor Details

    • EntityStatMap

      public EntityStatMap()
  • Method Details

    • getComponentType

      public static ComponentType<EntityStore, EntityStatMap> getComponentType()
    • getStatModifiersManager

      @Nonnull public StatModifiersManager getStatModifiersManager()
      Returns:
      the stat modifiers manager of this living entity.
    • size

      public int size()
    • get

      @Nullable public EntityStatValue get(int index)
      Returns the entity stat value for the given index or null if the stat doesn't exist in this map.
      Parameters:
      index - The index of the entity stat type to lookup.
      Returns:
      The stat value or null.
    • get

      @Deprecated @Nullable public EntityStatValue get(String entityStat)
      Deprecated.
      Should use get(int) and access stats by index instead of a string key.
    • update

      public void update()
      Updates this stat map with any changes to loaded EntityStatType assets.

      This will add any new stats, remove and removed stats and update the state of any existing stats with any changes to the asset type.

    • getModifier

      @Nullable public Modifier getModifier(int index, String key)
    • putModifier

      @Nullable public Modifier putModifier(int index, String key, Modifier modifier)
      Adds the given modifier to the entity stat specified by the given index.

      This will replace any existing modifiers with the same key.

      This does nothing if stat index is invalid.

      Parameters:
      index - The entity stat type index to add the modifier to.
      key - The key to give the modifier to be accessed later.
      modifier - The modifier to add.
      Returns:
      The modifier on that the stat previously with that key or null if there wasn't one.
    • putModifier

      @Nullable public Modifier putModifier(EntityStatMap.Predictable predictable, int index, String key, Modifier modifier)
      Adds the given modifier to the entity stat specified by the given index.

      This will replace any existing modifiers with the same key.

      This does nothing if stat index is invalid.

      Parameters:
      predictable - Sets how predictable this change is
      index - The entity stat type index to add the modifier to.
      key - The key to give the modifier to be accessed later.
      modifier - The modifier to add.
      Returns:
      The modifier on that the stat previously with that key or null if there wasn't one.
    • removeModifier

      @Nullable public Modifier removeModifier(int index, String key)
      Removes the modifier on the given stat with the given key.

      This does nothing if stat index is invalid.

      Parameters:
      index - The entity stat type index to remove the modifier from.
      key - The key of the modifier to remove.
      Returns:
      The removed modifier or null if no modifier was removed.
    • removeModifier

      @Nullable public Modifier removeModifier(EntityStatMap.Predictable predictable, int index, String key)
      Removes the modifier on the given stat with the given key.

      This does nothing if stat index is invalid.

      Parameters:
      predictable - Sets how predictable this change is
      index - The entity stat type index to remove the modifier from.
      key - The key of the modifier to remove.
      Returns:
      The removed modifier or null if no modifier was removed.
    • setStatValue

      public float setStatValue(int index, float newValue)
      Changes the value of the given stat to the new value.

      This does nothing if stat index is invalid.

      Parameters:
      index - The entity stat type index to change.
      newValue - The new value of the stat.
      Returns:
      The previous value of the stat.
    • setStatValue

      public float setStatValue(EntityStatMap.Predictable predictable, int index, float newValue)
      Changes the value of the given stat to the new value.

      This does nothing if stat index is invalid.

      Parameters:
      predictable - Sets how predictable this change is
      index - The entity stat type index to change.
      newValue - The new value of the stat.
      Returns:
      The previous value of the stat.
    • addStatValue

      public float addStatValue(int index, float amount)
      Add the given value to the specified stat.

      This does nothing if stat index is invalid.

      Parameters:
      index - The entity stat type index to change.
      amount - The amount to add to the stat value.
      Returns:
      The previous value of the stat.
    • addStatValue

      public float addStatValue(EntityStatMap.Predictable predictable, int index, float amount)
      Add the given value to the specified stat.

      This does nothing if stat index is invalid.

      Parameters:
      predictable - Sets how predictable this change is
      index - The entity stat type index to change.
      amount - The amount to add to the stat value.
      Returns:
      The previous value of the stat.
    • subtractStatValue

      public float subtractStatValue(int index, float amount)
      Subtracts the given value from the specified stat.

      This does nothing if stat index is invalid.

      Parameters:
      index - The entity stat type index to change.
      amount - The amount to add to the stat value.
      Returns:
      The previous value of the stat.
    • subtractStatValue

      public float subtractStatValue(EntityStatMap.Predictable predictable, int index, float amount)
      Subtracts the given value from the specified stat.

      This does nothing if stat index is invalid.

      Parameters:
      predictable - Sets how predictable this change is
      index - The entity stat type index to change.
      amount - The amount to add to the stat value.
      Returns:
      The previous value of the stat.
    • minStatValue

      public float minStatValue(int index, float value)
      Lowers the specified stat to the given value, leaving it unchanged if it is already at or below that value.

      This does nothing if stat index is invalid.

      Parameters:
      index - The entity stat type index to change.
      value - The value to cap the stat at.
      Returns:
      The previous value of the stat.
    • minStatValue

      public float minStatValue(EntityStatMap.Predictable predictable, int index, float value)
      Lowers the specified stat to the given value, leaving it unchanged if it is already at or below that value.

      This does nothing if stat index is invalid.

      Parameters:
      predictable - Sets how predictable this change is
      index - The entity stat type index to change.
      value - The value to cap the stat at.
      Returns:
      The previous value of the stat.
    • maxStatValue

      public float maxStatValue(int index, float value)
      Raises the specified stat to the given value, leaving it unchanged if it is already at or above that value.

      This does nothing if stat index is invalid.

      Parameters:
      index - The entity stat type index to change.
      value - The value to floor the stat at.
      Returns:
      The previous value of the stat.
    • maxStatValue

      public float maxStatValue(EntityStatMap.Predictable predictable, int index, float value)
      Raises the specified stat to the given value, leaving it unchanged if it is already at or above that value.

      This does nothing if stat index is invalid.

      Parameters:
      predictable - Sets how predictable this change is
      index - The entity stat type index to change.
      value - The value to floor the stat at.
      Returns:
      The previous value of the stat.
    • minimizeStatValue

      public float minimizeStatValue(int index)
      Changes the specified stat to its minimum value.

      This does nothing if stat index is invalid.

      Parameters:
      index - The entity stat type index to change.
      Returns:
      The previous value of the stat.
    • minimizeStatValue

      public float minimizeStatValue(EntityStatMap.Predictable predictable, int index)
      Changes the specified stat to its minimum value.

      This does nothing if stat index is invalid.

      Parameters:
      predictable - Sets how predictable this change is
      index - The entity stat type index to change.
      Returns:
      The previous value of the stat.
    • maximizeStatValue

      public float maximizeStatValue(int index)
      Changes the specified stat to its maximum value.

      This does nothing if stat index is invalid.

      Parameters:
      index - The entity stat type index to change.
      Returns:
      The previous value of the stat.
    • maximizeStatValue

      public float maximizeStatValue(EntityStatMap.Predictable predictable, int index)
      Changes the specified stat to its maximum value.

      This does nothing if stat index is invalid.

      Parameters:
      predictable - Sets how predictable this change is
      index - The entity stat type index to change.
      Returns:
      The previous value of the stat.
    • resetStatValue

      public float resetStatValue(int index)
      Changes the specified stat to its initial value.

      This does nothing if stat index is invalid.

      Parameters:
      index - The entity stat type index to change.
      Returns:
      The previous value of the stat.
    • resetStatValue

      public float resetStatValue(EntityStatMap.Predictable predictable, int index)
      Changes the specified stat to its initial value.

      This does nothing if stat index is invalid.

      Parameters:
      predictable - Sets how predictable this change is
      index - The entity stat type index to change.
      Returns:
      The previous value of the stat.
    • getSelfUpdates

      @Nonnull public it.unimi.dsi.fastutil.ints.Int2ObjectMap<List<EntityStatUpdate>> getSelfUpdates()
      Returns the current list of updates to entity stats.

      This list will be cleared when the system EntityStatsSystems.EntityTrackerUpdate runs so should be accessed before then.

      Returns:
      The list of updates to entity stats.
    • getSelfStatValues

      @Nonnull public it.unimi.dsi.fastutil.ints.Int2ObjectMap<it.unimi.dsi.fastutil.floats.FloatList> getSelfStatValues()
      Returns the current list of stat values.

      This list has the same length as the list returned by getSelfUpdates(). It can be used to see what the stat value was at the time the update finished applying.

      Returns:
      The list of previous stat values
    • consumeSelfUpdates

      @Nonnull public it.unimi.dsi.fastutil.ints.Int2ObjectMap<EntityStatUpdate[]> consumeSelfUpdates()
    • clearUpdates

      public void clearUpdates()
    • consumeOtherUpdates

      @Nonnull public it.unimi.dsi.fastutil.ints.Int2ObjectMap<EntityStatUpdate[]> consumeOtherUpdates()
    • createInitUpdate

      @Nonnull public it.unimi.dsi.fastutil.ints.Int2ObjectMap<EntityStatUpdate[]> createInitUpdate(boolean all)
    • isStatChangeSuppressed

      public boolean isStatChangeSuppressed(int index, @Nonnull StatChangeDirection direction)
    • setStatChangeSuppressed

      public void setStatChangeSuppressed(int index, @Nonnull StatChangeDirection direction, boolean suppressed)
    • consumeSelfNetworkOutdated

      public boolean consumeSelfNetworkOutdated()
    • consumeNetworkOutdated

      public boolean consumeNetworkOutdated()
    • processStatChanges

      public void processStatChanges(EntityStatMap.Predictable predictable, @Nonnull it.unimi.dsi.fastutil.ints.Int2FloatMap entityStats, ValueType valueType, @Nonnull ChangeStatBehaviour changeStatBehaviour)
    • toString

      @Nonnull public String toString()
      Overrides:
      toString in class Object
    • clone

      @Nonnull public EntityStatMap clone()
      Specified by:
      clone in interface Component<EntityStore>
      Returns:
      a clone instance of the original component instance.

    • toPacket

      @Nullable public static it.unimi.dsi.fastutil.ints.Int2ObjectMap<Modifier[]> toPacket(@Nullable it.unimi.dsi.fastutil.ints.Int2ObjectMap<StaticModifier[]> modifiers)