Table of Contents

Struct ObservedResourcePushScheduler

Namespace
FishMMO.Shared
Assembly
FishMMO.Shared.dll

Decides, tick by tick, whether a character's resources go out to its observers.

public struct ObservedResourcePushScheduler
Inherited Members

Remarks

The observer resource stream is unreliable and change gated: a value is sent when it changes and then never again. Lose that one packet and every observer holds a stale bar until the next change — which for a creature that has just died, or has just been topped up to full, may be never. This schedules a single confirmation re-send of the last pushed state ConfirmDelayTicks later, provided the state is still what was pushed. One confirmation is pending at most; a new change replaces it rather than stacking.

Pure state machine with no network dependency so the schedule is unit tested. The owner of this struct decides what "changed" means (whole units, for a bar) and passes it in.

Fields

ConfirmDelayTicks

Ticks after a push before its confirmation re-send. 15 at tick rate 30 is half a second.

public const uint ConfirmDelayTicks = 15

Field Value

uint

ConfirmPending

True while a confirmation re-send is scheduled for ConfirmTick.

public bool ConfirmPending

Field Value

bool

ConfirmTick

Tick the pending confirmation is due on.

public uint ConfirmTick

Field Value

uint

HasPushed

False until the first push, which always happens regardless of change.

public bool HasPushed

Field Value

bool

LastPushed

The state most recently sent.

public CharacterAttributeResourceState LastPushed

Field Value

CharacterAttributeResourceState

NextPushTick

Earliest tick the next change push may occur on.

public uint NextPushTick

Field Value

uint

Methods

AllowImmediatePush(uint)

Drops the outstanding rate limit so the next CHANGE is sent on the tick it happens.

public void AllowImmediatePush(uint tick)

Parameters

tick uint

The current server tick; the deadline is moved back to it.

Remarks

NextPushTick is an absolute deadline stamped from the interval in force at the last push. A caller that widens its interval while a character is idle therefore leaves a deadline behind that outlives the reason for it — and the event that matters most (the first hit of a fight) is exactly the one that arrives while it is still pending. This clears the deadline without pushing anything: nothing is sent unless the state has actually changed.

Deliberately does NOT touch LastPushed, HasPushed or the pending confirmation. Clearing those would resend a value the observers already hold and would drop the loss repair for the previous push.

Evaluate(uint, in CharacterAttributeResourceState, uint)

Evaluates one tick.

public ObservedResourcePushScheduler.Decision Evaluate(uint tick, in CharacterAttributeResourceState state, uint pushInterval)

Parameters

tick uint

The current server tick.

state CharacterAttributeResourceState

The current resource state, with fields observers do not use zeroed.

pushInterval uint

Minimum ticks between change pushes.

Returns

ObservedResourcePushScheduler.Decision

What, if anything, to send. On Push, LastPushed is now state.

Reset()

Forgets everything, so the next evaluation pushes unconditionally.

public void Reset()

ResourcesDifferForObservers(in CharacterAttributeResourceState, in CharacterAttributeResourceState)

True when two resource states differ by enough for an observer to notice.

public static bool ResourcesDifferForObservers(in CharacterAttributeResourceState a, in CharacterAttributeResourceState b)

Parameters

a CharacterAttributeResourceState
b CharacterAttributeResourceState

Returns

bool

Remarks

Compared at whole units because that is what a health bar renders. Sub-unit regeneration drift would otherwise mark every interval dirty and push continuously.