4 using System.Collections.Generic;
 
   10 public delegate 
void PropagateSpawnUpHandler (
int requestIndex, 
SpawnInfo spawnInfo);
 
   11 public delegate 
void PropagateSpawnDownHandler (
int requesterIndex, 
int requestIndex, 
int objectIndex, 
SpawnInfo spawnInfo);
 
   12 public delegate 
void PropagateDespawnUpHandler (
int objectIndex);
 
   13 public delegate 
void PropagateDespawnDownHandler (
int requesterIndex, 
int objectIndex);
 
   15 public partial class Sync : MonoBehaviour
 
   17     public static event PropagateSpawnUpHandler PropagateSpawnUp;
 
   18     public static event PropagateSpawnDownHandler PropagateSpawnDown;
 
   19     public static event PropagateDespawnUpHandler PropagateDespawnUp;
 
   20     public static event PropagateDespawnDownHandler PropagateDespawnDown;
 
   22     static int _localPeerIndex = -1;
 
   23     static bool _isClient;
 
   24     static bool _isServer;
 
   25     static bool _isMapSynced;
 
   26     static bool _isMapUnsyncing;
 
   29     static Dictionary<string, GameObject> _spawnablePrefabs;
 
   30     static Dictionary<string, UJeli> _spawnDetailsTemplates;
 
   31     static Dictionary<int, Sync> _syncedObjects;
 
   32     static Dictionary<int, Sync> _syncingObjects;
 
   33     static Dictionary<int, Sync> _requestedObjects;
 
   34     static Dictionary<int, Sync> _syncingMapObjects;
 
   35     static int _nextSpawnRequestIndex;
 
   36     static int _nextObjectIndex;
 
   37     static int _timelineObjectIndex;
 
   38     static byte _timelineScriptIndex;
 
   39     static byte _nextTimelineIndex;
 
   41     internal static void Initialize ()
 
   43         _spawnablePrefabs = 
new Dictionary<string, GameObject>();
 
   44         _spawnDetailsTemplates = 
new Dictionary<string, UJeli>();
 
   46         foreach (var prefab 
in Resources.LoadAll<GameObject>(
""))
 
   48             _spawnablePrefabs.Add(prefab.name, prefab);
 
   51         _syncedObjects = 
new Dictionary<int, Sync>();
 
   52         _syncingObjects = 
new Dictionary<int, Sync>();
 
   53         _requestedObjects = 
new Dictionary<int, Sync>();
 
   54         _syncingMapObjects = 
new Dictionary<int, Sync>();
 
   57     internal static void SetSpawnDetailsTemplate (
string prefabId, 
UJeli spawnDetailsTemplate)
 
   59         _spawnDetailsTemplates[prefabId] = spawnDetailsTemplate;
 
   62     internal static void SyncServer ()
 
   68         _timelineManager.ClockSyncCorrectionFactor = 50f;
 
   69         _timelineManager.MinClockSyncCorrectionRate = 50f;
 
   72         _timelineSyncer.ClockSyncSamplingRule = ClockSyncSamplingRule.MostRecent;
 
   73         _timelineSyncer.ConnectPeer(0, 0);
 
   80     internal static void BeginSyncClient (
int peerIndex)
 
   83         _localPeerIndex = peerIndex;
 
   86         _timelineManager.ClockSyncCorrectionFactor = 10f;
 
   87         _timelineManager.MinClockSyncCorrectionRate = 10f;
 
   89         _nextSpawnRequestIndex = 0;
 
   94     internal static void FinishSyncClient ()
 
   96         foreach (var sync 
in _syncingObjects.Values.ToArray())
 
   98             if (sync._spawnInfo == null && !_syncingMapObjects.ContainsValue(sync))
 
  100                 _syncingObjects.Remove(sync._objectIndex);
 
  101                 Destroy(sync.gameObject);
 
  105         _syncingMapObjects.Clear();
 
  110     private static void AddMapObjects ()
 
  112         var rootSyncsInScene = 
new List<Sync>(FindObjectsOfType<Sync>().Where(sync => sync.IsRoot));
 
  113         rootSyncsInScene.Sort((a, b) => a.name.CompareTo(b.name));
 
  115         _nextObjectIndex = -1;
 
  117         foreach (var sync 
in rootSyncsInScene)
 
  119             SetObjectOwner(sync, 0);
 
  122         foreach (var sync 
in rootSyncsInScene)
 
  125             SyncObject(sync, _nextObjectIndex, 
false);
 
  129     private static void RemoveMapObjects ()
 
  131         var rootSyncsInScene = 
new List<Sync>(FindObjectsOfType<Sync>().Where(sync => sync.IsRoot));
 
  133         foreach (var sync 
in rootSyncsInScene)
 
  135             if (sync._spawnInfo != null)
 
  142     internal static void RegisterClient (
int peerIndex, 
float rtt)
 
  144         _timelineSyncer.ConnectPeer((ushort)peerIndex, rtt);
 
  147     internal static void UnregisterClient (
int peerIndex)
 
  150         _timelineSyncer.DisconnectPeer((ushort)peerIndex);
 
  153     internal static void Step ()
 
  157             foreach (var timelineMsg 
in _timelineManager.GetOutgoingMessages())
 
  159                 _timelineSyncer.ProcessIncomingMessage(0, timelineMsg);
 
  162             foreach (var timelineMsg 
in _timelineSyncer.GetOutgoingMessages(0))
 
  164                 _timelineManager.ProcessIncomingMessage(timelineMsg);
 
  167             if (_timelineSyncer != null)
 
  168                 _timelineSyncer.Step(Time.deltaTime);
 
  171         _timelineManager.Step(Time.deltaTime);
 
  173         foreach (var sync 
in _syncingObjects.Values.ToArray())
 
  177             foreach (var essentialTimeline 
in sync._essentialTimelines)
 
  179                 if (essentialTimeline.NumEntries == 0)
 
  184                 FinalizeObject(sync, 
true);
 
  188     internal static void UnsyncClient ()
 
  190         _isMapUnsyncing = 
true;
 
  192         foreach (var sync 
in _syncedObjects.Values.ToArray())
 
  197             if (sync._spawnInfo != null)
 
  200                 Destroy(sync.gameObject);
 
  206         _syncingObjects.Clear();
 
  207         _syncingMapObjects.Clear();
 
  208         _syncedObjects.Clear();
 
  209         _requestedObjects.Clear();
 
  211         _localPeerIndex = -1;
 
  212         _timelineManager = null;
 
  213         _isMapSynced = 
false;
 
  214         _isMapUnsyncing = 
false;
 
  217     internal static void ProcessPropagatedUpSpawn (
int requesterIndex, 
int requestIndex, 
SpawnInfo spawnInfo)
 
  219         var sync = SpawnFromInfo(spawnInfo);
 
  222         SyncObject(sync, _nextObjectIndex, 
true);
 
  224         if (PropagateSpawnDown != null)
 
  225             PropagateSpawnDown(requesterIndex, requestIndex, sync._objectIndex, spawnInfo);
 
  228     internal static void ProcessPropagatedDownSpawn (
SpawnInfo spawnInfo, 
int objectIndex, 
bool isNew)
 
  232         if (spawnInfo != null)
 
  234             sync = SpawnFromInfo(spawnInfo);
 
  235             SyncObject(sync, objectIndex, isNew);
 
  239             _syncingObjects.TryGetValue(objectIndex, out sync);
 
  242                 _syncingMapObjects.Add(objectIndex, sync);
 
  246     internal static void ProcessSpawnRequestResponse (
int requestIndex, 
int objectIndex)
 
  250         if (!_requestedObjects.TryGetValue(requestIndex, out sync))
 
  256             if (PropagateDespawnUp != null)
 
  257                 PropagateDespawnUp(objectIndex);
 
  262         SyncObject(sync, objectIndex, 
true);
 
  265     internal static void ProcessPropagatedUpDespawn (
int requesterIndex, 
int objectIndex)
 
  269         if (!_syncedObjects.TryGetValue(objectIndex, out sync))
 
  272         if (PropagateDespawnDown != null)
 
  273             PropagateDespawnDown(requesterIndex, objectIndex);
 
  275         NotifyDespawn(sync.gameObject);
 
  277         Destroy(sync.gameObject);
 
  280     internal static void ProcessPropagatedDownDespawn (
int objectIndex)
 
  284         if (!_syncedObjects.TryGetValue(objectIndex, out sync))
 
  286             if (!_syncingObjects.TryGetValue(objectIndex, out sync))
 
  290         NotifyDespawn(sync.gameObject);
 
  292         Destroy(sync.gameObject);
 
  295     private static GameObject SpawnShell (GameObject prefab, Vector3 position)
 
  297         var go = (GameObject)Instantiate(prefab, position, prefab.transform.rotation);
 
  298         go.name = prefab.name;
 
  305         var sync = go.GetComponent<
Sync>();
 
  308             go.transform.SetDirection(spawnInfo.
Direction);
 
  311         sync._spawnInfo = spawnInfo;
 
  316     private static bool ShouldScriptExecute (
Sync sync, ScriptRole scriptRole)
 
  321         var isOwner = sync._ownerPeerIndex == _localPeerIndex;
 
  323         if (scriptRole == ScriptRole.Logic
 
  324             || scriptRole == ScriptRole.Owner)
 
  328         else if (scriptRole == ScriptRole.View
 
  329             || scriptRole == ScriptRole.Client)
 
  333         else if (scriptRole == ScriptRole.Secure
 
  334             || scriptRole == ScriptRole.Server)
 
  338         else if (scriptRole == ScriptRole.HumanBrain
 
  339             || scriptRole == ScriptRole.ClientOwner
 
  340             || scriptRole == ScriptRole.OwnerView)
 
  342             return isOwner && _isClient;
 
  344         else if (scriptRole == ScriptRole.BotBrain
 
  345             || scriptRole == ScriptRole.ServerOwner)
 
  347             return isOwner && _isServer;
 
  353     private static void SetObjectOwner (
Sync sync, 
int ownerPeerIndex)
 
  355         foreach (var childSync 
in sync.GetComponentsInChildren<
Sync>())
 
  357             childSync._ownerPeerIndex = ownerPeerIndex;
 
  360         foreach (var mb 
in sync._originalBehaviours)
 
  362             var mbType = mb.GetType();
 
  364             var scriptAttrs = mbType.GetCustomAttributes(typeof(
ScriptAttribute), 
false);
 
  366             if (scriptAttrs.Length != 0)
 
  369                 mb.enabled = ShouldScriptExecute(sync, scriptAttr.ScriptRole);
 
  371             else mb.enabled = 
true;
 
  375     private static void SyncObject (
Sync sync, 
int objectIndex, 
bool isNew)
 
  377         if (_timelineManager == null)
 
  380         foreach (var childSync 
in sync.GetComponentsInChildren<
Sync>())
 
  382             childSync._objectIndex = objectIndex;
 
  390         _syncingObjects.Add(objectIndex, sync);
 
  392         _timelineObjectIndex = objectIndex;
 
  393         _timelineScriptIndex = 0;
 
  395         foreach (var mb 
in sync._originalBehaviours)
 
  397             _nextTimelineIndex = 0;
 
  399             sync._timelines.AddRange(_timelineManager.AddTimelines(mb, GenerateTimelineID));
 
  401             sync._essentialTimelines.AddRange(
 
  402                 from timeline in sync._timelines
 
  403                 where timeline.Tags.Contains(
"Essential")
 
  406             _timelineScriptIndex++;
 
  409         if (sync._ownerPeerIndex == _localPeerIndex)
 
  410             FinalizeObject(sync, isNew);
 
  411         else sync.gameObject.SetActive(
false);
 
  414     private static byte[] GenerateTimelineID (
string s)
 
  416         byte[] 
id = BuildTimelineID(_timelineObjectIndex, _timelineScriptIndex, _nextTimelineIndex);
 
  417         _nextTimelineIndex++;
 
  421     private static byte[] BuildTimelineID (
int objectIndex, byte timelineScriptIndex, byte timelineIndex)
 
  423         byte[] 
id = 
new byte[6];
 
  425         Buffer.BlockCopy(BitConverter.GetBytes(objectIndex), 0, id, 0, 4);
 
  426         id[4] = timelineScriptIndex;
 
  427         id[5] = timelineIndex;
 
  432     private static void FinalizeObject (
Sync sync, 
bool isNew)
 
  434         _syncingObjects.Remove(sync._objectIndex);
 
  436         try { _syncedObjects.Add(sync._objectIndex, sync); }
 
  440             string errorMsg = e.Message;
 
  441             errorMsg += 
"\nAn error occurred while trying to Finalize Object: " + sync.name + 
", Object Index: " + sync._objectIndex + 
".";
 
  448         if (!sync.gameObject.activeSelf)
 
  449             sync.gameObject.SetActive(
true);
 
  451         if (sync._spawnInfo != null)
 
  453             PreAssignValues(sync.gameObject, sync._spawnInfo.
Details);
 
  454             NotifySpawn(sync.gameObject, sync._spawnInfo.
Details, isNew);
 
  457                 && sync._ownerPeerIndex == _localPeerIndex
 
  458                 && sync.rigidbody != null
 
  459                 && !sync.rigidbody.isKinematic
 
  460                 && sync._spawnInfo.
Details.HasChild(
"Velocity"))
 
  462                 sync.rigidbody.velocity = sync._spawnInfo.
Details[
"Velocity"].Vector3Value;
 
  467             PreAssignValues(sync.gameObject, 
new UJeli());
 
  468             NotifySpawn(sync.gameObject, 
new UJeli(), isNew);
 
  472     private static void PreAssignValues (GameObject go, 
UJeli details)
 
  474         foreach (var mb 
in go.GetComponentsInChildren<MonoBehaviour>())
 
  479             var mbType = mb.GetType();
 
  481             foreach (var field 
in mbType.GetFields(
 
  482                 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
 
  486                 if (spawnDetailAttrs.Length != 0)
 
  489                     string detailKey = spawnDetailAttr.
DetailKey ?? field.Name;
 
  491                     if (details.HasChild(detailKey))
 
  493                         var detail = details[detailKey];
 
  494                         SetFieldValueFromJeli(field, mb, detail);
 
  500                 if (mapSettingAttrs.Length != 0)
 
  503                     string settingKey = mapSettingAttr.
SettingKey ?? field.Name;
 
  505                     if (Game.MapSettings.HasChild(settingKey))
 
  507                         var setting = Game.MapSettings[settingKey];
 
  508                         SetFieldValueFromJeli(field, mb, setting);
 
  515     private static void SetFieldValueFromJeli (FieldInfo field, 
object obj, 
UJeli jeli)
 
  517         var fieldType = field.FieldType;
 
  521             if (fieldType == typeof(
int))
 
  522                 field.SetValue(obj, jeli.IntValue);
 
  523             else if (fieldType == typeof(uint))
 
  524                 field.SetValue(obj, jeli.UIntValue);
 
  525             else if (fieldType == typeof(
long))
 
  526                 field.SetValue(obj, jeli.LongValue);
 
  527             else if (fieldType == typeof(ulong))
 
  528                 field.SetValue(obj, jeli.ULongValue);
 
  529             else if (fieldType == typeof(
short))
 
  530                 field.SetValue(obj, jeli.ShortValue);
 
  531             else if (fieldType == typeof(ushort))
 
  532                 field.SetValue(obj, jeli.UShortValue);
 
  533             else if (fieldType == typeof(
float))
 
  534                 field.SetValue(obj, jeli.FloatValue);
 
  535             else if (fieldType == typeof(
double))
 
  536                 field.SetValue(obj, jeli.DoubleValue);
 
  537             else if (fieldType == typeof(byte))
 
  538                 field.SetValue(obj, jeli.ByteValue);
 
  539             else if (fieldType == typeof(sbyte))
 
  540                 field.SetValue(obj, jeli.SByteValue);
 
  541             else if (fieldType == typeof(
bool))
 
  542                 field.SetValue(obj, jeli.BoolValue);
 
  543             else if (fieldType == typeof(
string))
 
  544                 field.SetValue(obj, jeli.Value);
 
  545             else if (fieldType == typeof(
char))
 
  546                 field.SetValue(obj, jeli.CharValue);
 
  547             else if (fieldType.IsEnum)
 
  548                 field.SetValue(obj, Enum.Parse(fieldType, jeli.Value));
 
  549             else if (fieldType == typeof(DateTime))
 
  550                 field.SetValue(obj, jeli.TimeValue);
 
  551             else if (fieldType == typeof(Vector2))
 
  552                 field.SetValue(obj, jeli.Vector2Value);
 
  553             else if (fieldType == typeof(Vector3))
 
  554                 field.SetValue(obj, jeli.Vector3Value);
 
  555             else if (fieldType == typeof(Vector4))
 
  556                 field.SetValue(obj, jeli.Vector4Value);
 
  557             else if (fieldType == typeof(Quaternion))
 
  558                 field.SetValue(obj, jeli.QuaternionValue);
 
  559             else if (fieldType == typeof(Matrix4x4))
 
  560                 field.SetValue(obj, jeli.MatrixValue);
 
  561             else if (fieldType == typeof(Ray))
 
  562                 field.SetValue(obj, jeli.RayValue);
 
  563             else if (fieldType == typeof(Color))
 
  564                 field.SetValue(obj, jeli.ColorValue);
 
  565             else if (fieldType == typeof(GameObject))
 
  566                 field.SetValue(obj, jeli.GameObjectValue);
 
  571     private static void NotifySpawn (GameObject go, 
UJeli details, 
bool isNew)
 
  576     private static void NotifyDespawn (GameObject go)
 
  583     private static void UnsyncObject (
Sync sync)
 
  588         if (_timelineManager == null)
 
  591         foreach (var timeline 
in sync._timelines)
 
  593             _timelineManager.Remove(timeline);
 
  596         sync._timelines.Clear();
 
  597         sync._essentialTimelines.Clear();
 
  599         _syncedObjects.Remove(sync._objectIndex);
 
  600         _syncingObjects.Remove(sync._objectIndex);
 
  602         foreach (var childSync 
in sync.GetComponentsInChildren<
Sync>())
 
  604             childSync._objectIndex = -1;
 
static void DespawnPeerObjects(int peerIndex)
Despawn all objects owned by the peer with the given peer index. 
 
GameObject Prefab
The prefab from which this object is instantiated. 
 
Attribute to use on fields. Marks them for assignment from map settings. 
 
string DetailKey
Gets the detail key used to find the value for the target field. 
 
Marks a MonoBehaviour as a game script with a given script role. 
 
static void SendEnabledMessage(GameObject go, string message, params object[] args)
Invokes a method on all enabled scripts in the GameObject. 
 
Vector3 Position
The position at which this object was spawned. 
 
Attribute to use on fields. Marks them for assignment from spawn details. 
 
static TimelineSynchronizer TimelineSynchronizer
Gets the Janus timeline synchronizer if this is the server. 
 
void DisconnectFromServer()
Disconnect from the current server. 
 
static GameClient Instance
Gets the sole instance of the game client. 
 
string SettingKey
Gets the setting key used to find the value for the target field. 
 
int OwnerPeerIndex
The peer index of the peer which owns this object. 
 
Vector3 Direction
The direction this object was facing when it was spawned. 
 
static GameObject GetObject(int objectIndex)
Get an object by its object index. 
 
Unity version of Jeli markup class. 
 
static TimelineManager TimelineManager
Gets the Janus timeline manager on this peer. 
 
This class server two main functions: 1) As a MonoBehaviour, it allows for network synchronization of...
 
The spawn-time information of a spawned object. 
 
UJeli Details
Additional spawn details.