summaryrefslogtreecommitdiff
path: root/ROUNDS/Photon.Pun.Simple/SyncVitals.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ROUNDS/Photon.Pun.Simple/SyncVitals.cs')
-rw-r--r--ROUNDS/Photon.Pun.Simple/SyncVitals.cs339
1 files changed, 339 insertions, 0 deletions
diff --git a/ROUNDS/Photon.Pun.Simple/SyncVitals.cs b/ROUNDS/Photon.Pun.Simple/SyncVitals.cs
new file mode 100644
index 0000000..342019d
--- /dev/null
+++ b/ROUNDS/Photon.Pun.Simple/SyncVitals.cs
@@ -0,0 +1,339 @@
+using System;
+using System.Collections.Generic;
+using Photon.Compression;
+using Photon.Pun.Simple.ContactGroups;
+using UnityEngine;
+
+namespace Photon.Pun.Simple;
+
+public class SyncVitals : SyncObject<SyncVitals.Frame>, IVitalsSystem, IContactSystem, IOnSnapshot, IOnNetSerialize, IOnAuthorityChanged, IOnPostSimulate, IOnVitalValueChange, IOnVitalChange, IOnCaptureState, IUseKeyframes, IOnStateChange
+{
+ public class Frame : FrameBase
+ {
+ public VitalsData vitalsData;
+
+ public Frame()
+ {
+ }
+
+ public Frame(int frameId)
+ : base(frameId)
+ {
+ }
+
+ public Frame(int frameId, Vitals vitals)
+ : base(frameId)
+ {
+ vitalsData = new VitalsData(vitals);
+ }
+
+ public override void CopyFrom(FrameBase sourceFrame)
+ {
+ base.CopyFrom(sourceFrame);
+ VitalsData source = (sourceFrame as Frame).vitalsData;
+ vitalsData.CopyFrom(source);
+ }
+ }
+
+ public Vitals vitals = new Vitals();
+
+ [SerializeField]
+ protected ContactGroupMaskSelector contactGroups;
+
+ [Tooltip("Vital triggers/pickups must have this as a valid mount type. When pickups will attach to this mount when picked up.")]
+ public MountSelector defaultMounting = new MountSelector(0);
+
+ [Tooltip("When root vital <= zero, syncState.Despawn() will be called. This allows for a default handling of object 'death'.")]
+ public bool autoDespawn = true;
+
+ [Tooltip("When OnStateChange changes from ObjState.Despawned to any other state, vital values will be reset to their starting defaults.")]
+ public bool resetOnSpawn = true;
+
+ [NonSerialized]
+ private VitalsData lastSentData;
+
+ public List<IOnVitalsValueChange> OnVitalsValueChange = new List<IOnVitalsValueChange>(0);
+
+ public List<IOnVitalsParamChange> OnVitalsParamChange = new List<IOnVitalsParamChange>(0);
+
+ public List<IOnRootVitalBecameZero> OnRootVitalBecameZero = new List<IOnRootVitalBecameZero>(0);
+
+ protected SyncState syncState;
+
+ private Vital[] vitalArray;
+
+ protected Vital rootVital;
+
+ private int vitalsCount;
+
+ protected int defaultMountingMask;
+
+ protected bool isPredicted;
+
+ private bool wasDespawned;
+
+ public override int ApplyOrder => 15;
+
+ public override bool AllowReconstructionOfEmpty => false;
+
+ public byte SystemIndex { get; set; }
+
+ public Vitals Vitals => vitals;
+
+ public IContactGroupMask ValidContactGroups => contactGroups;
+
+ public int ValidMountsMask => 1 << defaultMounting.id;
+
+ public Mount DefaultMount { get; set; }
+
+ protected override void PopulateFrames()
+ {
+ int frameCount = TickEngineSettings.frameCount;
+ frames = new Frame[frameCount + 1];
+ for (int i = 0; i <= frameCount; i++)
+ {
+ frames[i] = new Frame(i, vitals);
+ }
+ }
+
+ public override void OnAwake()
+ {
+ base.OnAwake();
+ base.transform.EnsureRootComponentExists<ContactManager, NetObject>();
+ if ((bool)netObj)
+ {
+ syncState = netObj.GetComponent<SyncState>();
+ }
+ vitalArray = vitals.VitalArray;
+ vitalsCount = vitals.vitalDefs.Count;
+ rootVital = vitalArray[0];
+ vitals.OnVitalValueChangeCallbacks.Add(this);
+ lastSentData = new VitalsData(vitals);
+ for (int i = 0; i < vitalsCount; i++)
+ {
+ vitalArray[i].ResetValues();
+ }
+ defaultMountingMask = 1 << defaultMounting.id;
+ }
+
+ public override void OnStart()
+ {
+ base.OnStart();
+ MountsManager component = GetComponent<MountsManager>();
+ if ((bool)component)
+ {
+ if (component.mountIdLookup.ContainsKey(defaultMounting.id))
+ {
+ DefaultMount = component.mountIdLookup[defaultMounting.id];
+ return;
+ }
+ Debug.LogWarning("Sync Vitals has a Default Mount setting of " + MountSettings.GetName(defaultMounting.id) + " but no such mount is defined yet on GameObject: '" + base.name + "'. Root mount will be used as a failsafe.");
+ defaultMounting.id = 0;
+ DefaultMount = component.mountIdLookup[0];
+ }
+ }
+
+ public override void OnAuthorityChanged(bool isMine, bool controllerChanged)
+ {
+ base.OnAuthorityChanged(isMine, controllerChanged);
+ OwnedIVitals.OnChangeAuthority(this, isMine, controllerChanged);
+ }
+
+ public Consumption TryTrigger(IContactReactor icontactReactor, ContactEvent contactEvent, int compatibleMounts)
+ {
+ if (!(icontactReactor is IVitalsContactReactor vitalsContactReactor))
+ {
+ return Consumption.None;
+ }
+ if ((int)contactGroups != 0)
+ {
+ int num = contactEvent.contactTrigger.ContactGroupsAssign?.Mask ?? 0;
+ if ((contactGroups.Mask & num) == 0)
+ {
+ return Consumption.None;
+ }
+ }
+ if (compatibleMounts != defaultMountingMask && (compatibleMounts & defaultMountingMask) == 0)
+ {
+ return Consumption.None;
+ }
+ Vital vital = vitals.GetVital(vitalsContactReactor.VitalNameType);
+ if (vital == null)
+ {
+ return Consumption.None;
+ }
+ double amountConsumed;
+ if (base.IsMine)
+ {
+ double discharge = vitalsContactReactor.DischargeValue(contactEvent.contactType);
+ amountConsumed = vitals.ApplyCharges(discharge, vitalsContactReactor.AllowOverload, vitalsContactReactor.Propagate);
+ }
+ else
+ {
+ amountConsumed = vital.TestApplyChange(vitalsContactReactor, contactEvent);
+ }
+ if (icontactReactor is IVitalsConsumable iva)
+ {
+ return TestConsumption(amountConsumed, iva, contactEvent);
+ }
+ return Consumption.None;
+ }
+
+ protected Consumption TestConsumption(double amountConsumed, IVitalsConsumable iva, ContactEvent contactEvent)
+ {
+ Consumption consumption = iva.Consumption;
+ double num = iva.DischargeValue(contactEvent.contactType);
+ switch (consumption)
+ {
+ case Consumption.None:
+ return Consumption.None;
+ case Consumption.All:
+ if (amountConsumed != 0.0)
+ {
+ iva.Charges = 0.0;
+ return Consumption.All;
+ }
+ return Consumption.None;
+ default:
+ {
+ int result = ((amountConsumed != 0.0) ? ((num != amountConsumed) ? 1 : 3) : 0);
+ iva.Charges -= amountConsumed;
+ return (Consumption)result;
+ }
+ }
+ }
+
+ public Mount TryPickup(IContactReactor reactor, ContactEvent contactEvent)
+ {
+ return DefaultMount;
+ }
+
+ public void OnPostSimulate(int frameId, int subFrameId, bool isNetTick)
+ {
+ if (isNetTick)
+ {
+ vitals.Simulate();
+ }
+ }
+
+ public virtual void OnCaptureCurrentState(int frameId)
+ {
+ VitalData[] datas = frames[frameId].vitalsData.datas;
+ for (int i = 0; i < vitalsCount; i++)
+ {
+ datas[i] = vitalArray[i].VitalData;
+ }
+ }
+
+ public SerializationFlags OnNetSerialize(int frameId, byte[] buffer, ref int bitposition, SerializationFlags writeFlags)
+ {
+ if (!base.enabled)
+ {
+ buffer.WriteBool(b: false, ref bitposition);
+ return SerializationFlags.None;
+ }
+ Frame frame = frames[frameId];
+ buffer.WriteBool(b: true, ref bitposition);
+ bool keyframe = IsKeyframe(frameId);
+ return vitals.Serialize(frame.vitalsData, lastSentData, buffer, ref bitposition, keyframe);
+ }
+
+ public SerializationFlags OnNetDeserialize(int originFrameId, byte[] buffer, ref int bitposition, FrameArrival arrival)
+ {
+ Frame frame = (base.IsMine ? offtickFrame : frames[originFrameId]);
+ if (!buffer.ReadBool(ref bitposition))
+ {
+ return SerializationFlags.None;
+ }
+ bool keyframe = IsKeyframe(originFrameId);
+ SerializationFlags serializationFlags = vitals.Deserialize(frame.vitalsData, buffer, ref bitposition, keyframe);
+ frame.content = (((serializationFlags & SerializationFlags.IsComplete) != 0) ? FrameContents.Complete : (((serializationFlags & SerializationFlags.HasContent) != 0) ? FrameContents.Partial : FrameContents.Empty));
+ return serializationFlags;
+ }
+
+ [Obsolete("Use vitals.ApplyCharges() instead")]
+ public double ApplyDamage(double damage)
+ {
+ if (!base.IsMine)
+ {
+ return damage;
+ }
+ if (damage == 0.0)
+ {
+ return damage;
+ }
+ return vitals.ApplyCharges(damage, allowOverload: false, propagate: true);
+ }
+
+ public void OnVitalValueChange(Vital vital)
+ {
+ if (vital.VitalData.Value <= 0.0)
+ {
+ RootVitalBecameZero(vital);
+ }
+ int i = 0;
+ for (int count = OnVitalsValueChange.Count; i < count; i++)
+ {
+ OnVitalsValueChange[i].OnVitalValueChange(vital);
+ }
+ }
+
+ public void OnVitalParamChange(Vital vital)
+ {
+ Debug.LogError("Not implemented");
+ int i = 0;
+ for (int count = OnVitalsParamChange.Count; i < count; i++)
+ {
+ OnVitalsParamChange[i].OnVitalParamChange(vital);
+ }
+ }
+
+ protected virtual void RootVitalBecameZero(Vital vital)
+ {
+ int i = 0;
+ for (int count = OnRootVitalBecameZero.Count; i < count; i++)
+ {
+ OnRootVitalBecameZero[i].OnRootVitalBecameZero(vital, null);
+ }
+ if (autoDespawn && (bool)syncState && rootVital == vital)
+ {
+ syncState.Despawn(immediate: false);
+ }
+ }
+
+ public void OnStateChange(ObjState newState, ObjState previousState, Transform attachmentTransform, Mount attachTo = null, bool isReady = true)
+ {
+ if (wasDespawned && newState != 0)
+ {
+ for (int i = 0; i < vitalsCount; i++)
+ {
+ vitalArray[i].ResetValues();
+ }
+ }
+ wasDespawned = newState == ObjState.Despawned;
+ }
+
+ protected override void ApplySnapshot(Frame snapframe, Frame targframe, bool snapIsValid, bool targIsValid)
+ {
+ if (snapIsValid && snapframe.content >= FrameContents.Extrapolated)
+ {
+ vitals.Apply(snapFrame.vitalsData);
+ }
+ }
+
+ protected override void InterpolateFrame(Frame targframe, Frame startframe, Frame endframe, float t)
+ {
+ targframe.CopyFrom(startframe);
+ }
+
+ protected override void ExtrapolateFrame(Frame prevframe, Frame snapframe, Frame targframe)
+ {
+ VitalData[] datas = snapframe.vitalsData.datas;
+ VitalData[] datas2 = targframe.vitalsData.datas;
+ for (int i = 0; i < vitalsCount; i++)
+ {
+ datas2[i] = vitalArray[i].VitalDef.Extrapolate(datas[i]);
+ }
+ targframe.content = FrameContents.Extrapolated;
+ }
+}