diff --git a/Assets/GWConquest/Scripts/BoltList.cs b/Assets/GWConquest/Scripts/BoltList.cs index 16741a5..b819411 100644 --- a/Assets/GWConquest/Scripts/BoltList.cs +++ b/Assets/GWConquest/Scripts/BoltList.cs @@ -46,7 +46,7 @@ namespace GWConquest set { Token.entries[index] = value; - Token = Token; + Token = new TokenClass().SetEntries(Token.entries) as TokenClass; } } @@ -117,6 +117,11 @@ namespace GWConquest { return new GenericListEnumerator(this); } + + public override string ToString() + { + return "BoltList " + Util.PrintEnumerable(this); + } } public abstract class BoltListToken : IProtocolToken @@ -136,25 +141,25 @@ namespace GWConquest public void Read(UdpPacket packet) { - BoltLog.Info("Reading Bolt list..."); + //BoltLog.Info("Reading Bolt list..."); int count = packet.ReadInt(); entries = new T[count]; for (int i = 0; i < count; i++) { entries[i] = ReadEntry(packet); } - BoltLog.Info("Finished reading Bolt list {0}", this); + //BoltLog.Info("Finished reading Bolt list {0}", this); } public void Write(UdpPacket packet) { - BoltLog.Info("Writing Bolt list..."); + //BoltLog.Info("Writing Bolt list..."); packet.WriteInt(entries.Length); foreach (T e in entries) { WriteEntry(packet, e); } - BoltLog.Info("Finished writing Bolt list {0}", this); + //BoltLog.Info("Finished writing Bolt list {0}", this); } public override string ToString() @@ -162,6 +167,32 @@ namespace GWConquest return "BoltList " + Util.PrintEnumerable(entries); } + public override bool Equals(object obj) + { + if(obj == null || !(obj is BoltListToken)) + return false; + + var other = obj as BoltListToken; + + if(entries.Length != other.entries.Length) + return false; + + for(int i = 0; i < entries.Length; i++) + { + if(entries[i] == null) + { + if(other.entries[i] != null) + return false; + } + else { + if(!entries[i].Equals(other.entries[i])) + return false; + } + } + + return true; + } + public abstract T ReadEntry(UdpPacket packet); public abstract void WriteEntry(UdpPacket packet, T entry); diff --git a/Assets/GWConquest/Scripts/Formation.cs b/Assets/GWConquest/Scripts/Formation.cs index dbb30fa..4d03062 100644 --- a/Assets/GWConquest/Scripts/Formation.cs +++ b/Assets/GWConquest/Scripts/Formation.cs @@ -8,6 +8,8 @@ namespace GWConquest { public class Formation : GWBoltBehaviour, IMovable { + public static List AllFormations = new List(); + private Zone lastZone; public Zone currentZone { @@ -120,7 +122,10 @@ namespace GWConquest public float movementSpeed = 1f; - public int formationNumber; + public int FormationNumber { + get => State.FormationNumber; + set => State.FormationNumber = value; + } public bool keepFormationName = false; [System.NonSerialized] @@ -404,6 +409,8 @@ namespace GWConquest PathQueue = new ZoneList(State, "PathQueue"); + AllFormations.Add(this); + if(entity.IsOwner) { State.CurrentZone = -1; @@ -411,7 +418,7 @@ namespace GWConquest CoveredDistance = 0; - formationNumber = UnityEngine.Random.Range(1, 100); + FormationNumber = UnityEngine.Random.Range(1, 100); } State.AddCallback("IsInTransit", OnTransitStateChanged); @@ -423,7 +430,15 @@ namespace GWConquest { if(entity.IsAttached) { - return UnitEntities.Sum(unit => unit.Entity.GetComponent().Class.UnitStrength); + return UnitEntities.Sum(unit => { + if(unit.Entity != null && unit.Entity.IsAttached) + { + return unit.Entity.GetComponent().Class.UnitStrength; + } + else { + return 0f; + } + }); } else { return 0f; @@ -525,7 +540,7 @@ namespace GWConquest public void ConstructName() { - string name = Util.GetOrdinalString(formationNumber) + " "; + string name = Util.GetOrdinalString(FormationNumber) + " "; name += FormationCategories.Instance.GetCategoryEntry(Category).Name + " "; @@ -581,6 +596,13 @@ namespace GWConquest State.FormationName = name; } + public override string ToString() + { + return string.Format("Formation {0} [{1}]", FormationName, Player); + } + + + } diff --git a/Assets/GWConquest/Scripts/GameManager.cs b/Assets/GWConquest/Scripts/GameManager.cs index c3cd6e1..1654559 100644 --- a/Assets/GWConquest/Scripts/GameManager.cs +++ b/Assets/GWConquest/Scripts/GameManager.cs @@ -1,4 +1,5 @@ using UnityEngine; +using System.Collections; namespace GWConquest { @@ -6,6 +7,10 @@ namespace GWConquest { public static int HostFactionIndex = 0; + public static bool EntitiesLoaded = false; + + public static int InitialEntityCount = -1; + public Faction[] Factions; public UnitClass[] UnitClasses; @@ -64,10 +69,11 @@ namespace GWConquest BoltLog.Info("Setup planet pathfinding."); } - public void OnSceneLoadLocalDone() + public void SceneLoadLocalDone() { if(SpawnAIPlayer) { + BoltLog.Info("Spawning AI players..."); for(int i = 0; i < Factions.Length; i++) { var faction = Factions[i]; @@ -80,10 +86,19 @@ namespace GWConquest playerEntity.GetComponent().AssignStartingPlanets(); } } - } - BoltLog.Info("Scene load done."); + } + + public void SetEntitiesLoaded() + { + StartCoroutine(EntitiesLoadedAsync()); + } + + private IEnumerator EntitiesLoadedAsync() + { + yield return new WaitForFixedUpdate(); + EntitiesLoaded = true; } } diff --git a/Assets/GWConquest/Scripts/GlobalCallbacks.cs b/Assets/GWConquest/Scripts/GlobalCallbacks.cs index 92607a0..041e394 100644 --- a/Assets/GWConquest/Scripts/GlobalCallbacks.cs +++ b/Assets/GWConquest/Scripts/GlobalCallbacks.cs @@ -1,4 +1,7 @@ -using UnityEngine; +using Bolt; +using UdpKit; +using UnityEngine; +using System.Linq; namespace GWConquest { @@ -15,9 +18,45 @@ namespace GWConquest public override void SceneLoadLocalDone(string scene) { + //BoltLog.Info("scene load token: {0}", token); + GameOptions.ApplyOptions(); GameManager.Instance.OnSceneLoadDoneAll(); } + + public override void SessionConnected(UdpSession session, IProtocolToken token) + { + BoltLog.Info("Session connected."); + } + + public override void OnEvent(ServerConfigEvent evnt) + { + if(BoltNetwork.IsClient) + { + GameManager.InitialEntityCount = evnt.EntityCount; + } + } + + public override void EntityReceived(BoltEntity entity) + { + if(BoltNetwork.IsClient && !GameManager.EntitiesLoaded) + { + var ecount = BoltNetwork.Entities.Count(); + if(ecount >= GameManager.InitialEntityCount) + { + BoltLog.Info("All entities retrieved!"); + GameManager.Instance.SetEntitiesLoaded(); + } + } + } + + + + + + + + } } \ No newline at end of file diff --git a/Assets/GWConquest/Scripts/Inventory.cs b/Assets/GWConquest/Scripts/Inventory.cs index ae264d6..ddb0b93 100644 --- a/Assets/GWConquest/Scripts/Inventory.cs +++ b/Assets/GWConquest/Scripts/Inventory.cs @@ -7,7 +7,7 @@ using UnityEngine; namespace GWConquest { [System.Serializable] - public class ItemStack : IIconObject, IProtocolToken + public struct ItemStack : IIconObject, IProtocolToken { public static int MaxStackSize { get => GameManager.Instance.MaxStackSize; @@ -15,7 +15,12 @@ namespace GWConquest public bool IsUnit; public string ItemName; - public Unit Unit; + public NetworkId UnitId; + + public Unit Unit + { + get => BoltNetwork.FindEntity(UnitId)?.GetComponent(); + } public bool Stackable; public int Amount; @@ -74,7 +79,7 @@ namespace GWConquest { return new ItemStack { IsUnit = true, - Unit = unit, + UnitId = unit.entity.NetworkId, Stackable = false, Amount = 1 }; @@ -83,7 +88,7 @@ namespace GWConquest public ItemStack Copy() { return new ItemStack() { IsUnit = IsUnit, - Unit = Unit, + UnitId = UnitId, ItemName = ItemName, Stackable = Stackable, Amount = Amount @@ -103,7 +108,7 @@ namespace GWConquest packet.WriteBool(IsUnit); if(IsUnit) { - packet.WriteULong(Unit.entity.NetworkId.PackedValue); + packet.WriteULong(UnitId.PackedValue); } else { packet.WriteString(ItemName); @@ -118,7 +123,7 @@ namespace GWConquest IsUnit = packet.ReadBool(); if(IsUnit) { - Unit = BoltNetwork.FindEntity(new NetworkId(packet.ReadULong()))?.GetComponent(); + UnitId = new NetworkId(packet.ReadULong()); } else { ItemName = packet.ReadString(); @@ -176,20 +181,24 @@ namespace GWConquest public bool AddItem(string item, int amount) { if(DoesItemFit(item, amount)) { - foreach(var stack in this) + for(int i = 0; i < Count; i++) { + var stack = this[i]; if(!stack.IsUnit && stack.ItemName == item) { int remainingRoom = ItemStack.MaxStackSize - stack.Amount; if(remainingRoom >= amount) { stack.Amount += amount; + this[i] = stack; return true; } else { amount -= remainingRoom; stack.Amount = ItemStack.MaxStackSize; + this[i] = stack; } + } } @@ -220,7 +229,9 @@ namespace GWConquest if(dict.ContainsKey(stack.ItemName)) { - dict[stack.ItemName].Amount += stack.Amount; + var s = dict[stack.ItemName]; + s.Amount += stack.Amount; + dict[stack.ItemName] = s; } else { dict[stack.ItemName] = stack.Copy(); diff --git a/Assets/GWConquest/Scripts/Planet.cs b/Assets/GWConquest/Scripts/Planet.cs index 321a5c6..ca0b997 100644 --- a/Assets/GWConquest/Scripts/Planet.cs +++ b/Assets/GWConquest/Scripts/Planet.cs @@ -174,13 +174,25 @@ namespace GWConquest public event Action FormationsChanged; + private bool formationsChangedSinceLastFrame = true; + public void OnFormationsChanged() { - FormationsChanged?.Invoke(); + formationsChangedSinceLastFrame = true; + } - if (indicatorUI != null) + private void FixedUpdate() + { + if(GameManager.EntitiesLoaded && formationsChangedSinceLastFrame) { - indicatorUI.UpdateIndicator(); + FormationsChanged?.Invoke(); + + if (indicatorUI != null) + { + indicatorUI.UpdateIndicator(); + } + + formationsChangedSinceLastFrame = false; } } diff --git a/Assets/GWConquest/Scripts/PlanetConnection.cs b/Assets/GWConquest/Scripts/PlanetConnection.cs index e0110c9..cd9b71f 100644 --- a/Assets/GWConquest/Scripts/PlanetConnection.cs +++ b/Assets/GWConquest/Scripts/PlanetConnection.cs @@ -29,7 +29,7 @@ namespace GWConquest private Color neutralColor; private void FixedUpdate() { - if(Application.isPlaying) + if(Application.isPlaying && GameManager.EntitiesLoaded) { Color color1 = neutralColor; Color color2 = neutralColor; diff --git a/Assets/GWConquest/Scripts/Player.cs b/Assets/GWConquest/Scripts/Player.cs index f96e72f..5eff173 100644 --- a/Assets/GWConquest/Scripts/Player.cs +++ b/Assets/GWConquest/Scripts/Player.cs @@ -100,7 +100,7 @@ namespace GWConquest public override string ToString() { - return string.Format("Player (ID {0}, Faction {1})", state.PlayerId, Faction.FactionName); + return string.Format("Player (ID {0}, Faction {1})", State.PlayerId, Faction.FactionName); } } diff --git a/Assets/GWConquest/Scripts/ServerCallbacks.cs b/Assets/GWConquest/Scripts/ServerCallbacks.cs index d0e487d..8189ddc 100644 --- a/Assets/GWConquest/Scripts/ServerCallbacks.cs +++ b/Assets/GWConquest/Scripts/ServerCallbacks.cs @@ -17,9 +17,23 @@ namespace GWConquest playerEntity.GetComponent().AssignStartingPlanets(); playerEntity.TakeControl(); + GameManager.Instance.SceneLoadLocalDone(); + foreach(GameObject go in FindObjectsOfType()) { go.SendMessage("OnSceneLoadLocalDone", SendMessageOptions.DontRequireReceiver); } + + var ecount = BoltNetwork.Entities.Count(); + + GameManager.InitialEntityCount = ecount; + + var configEvnt = ServerConfigEvent.Create(Bolt.GlobalTargets.AllClients); + configEvnt.EntityCount = ecount; + configEvnt.Send(); + + GameManager.EntitiesLoaded = true; + + BoltLog.Info("Server scene loading done."); } public override void SceneLoadRemoteDone(BoltConnection connection) @@ -55,7 +69,7 @@ namespace GWConquest } if(evnt.TargetFormation != null) { - formation.state.MovementTargetFormation = evnt.TargetFormation; + formation.State.MovementTargetFormation = evnt.TargetFormation; } } diff --git a/Assets/GWConquest/Scripts/UI/BalanceUI.cs b/Assets/GWConquest/Scripts/UI/BalanceUI.cs index 27d6819..28969ad 100644 --- a/Assets/GWConquest/Scripts/UI/BalanceUI.cs +++ b/Assets/GWConquest/Scripts/UI/BalanceUI.cs @@ -12,33 +12,37 @@ namespace GWConquest public MoneyDisplay FuelDisplay; private void FixedUpdate() { - var currentPlayer = Player.CurrentPlayer; - - if(currentPlayer != null) + if(GameManager.EntitiesLoaded) { - CreditsDisplay.Total = currentPlayer.Credits; - - int totalFood = 0; - int totalSupplies = 0; - int totalFuel = 0; + var currentPlayer = Player.CurrentPlayer; - foreach(var d in District.AllDistricts) + if(currentPlayer != null) { - if(d.ControllingPlayer == currentPlayer) + CreditsDisplay.Total = currentPlayer.Credits; + + int totalFood = 0; + int totalSupplies = 0; + int totalFuel = 0; + + foreach(var d in District.AllDistricts) { - totalFood += d.Inventory.GetItemAmount("Food"); - totalSupplies += d.Inventory.GetItemAmount("Supplies"); - totalFuel += d.Inventory.GetItemAmount("Fuel"); + if(d.ControllingPlayer == currentPlayer) + { + totalFood += d.Inventory.GetItemAmount("Food"); + totalSupplies += d.Inventory.GetItemAmount("Supplies"); + totalFuel += d.Inventory.GetItemAmount("Fuel"); + } } - } - //var query = Zone.AllZones.Select(z => z.GetComponent()) - // .Where(d => d != null && d.ControllingPlayer == currentPlayer) - // .SelectMany(d => d.Inventory); + //var query = Zone.AllZones.Select(z => z.GetComponent()) + // .Where(d => d != null && d.ControllingPlayer == currentPlayer) + // .SelectMany(d => d.Inventory); + + FoodDisplay.Total = totalFood; + SuppliesDisplay.Total = totalSupplies; + FuelDisplay.Total = totalFuel; + } - FoodDisplay.Total = totalFood; - SuppliesDisplay.Total = totalSupplies; - FuelDisplay.Total = totalFuel; } diff --git a/Assets/GWConquest/Scripts/UI/FormationIcon.cs b/Assets/GWConquest/Scripts/UI/FormationIcon.cs index 6c4923d..b5fb487 100644 --- a/Assets/GWConquest/Scripts/UI/FormationIcon.cs +++ b/Assets/GWConquest/Scripts/UI/FormationIcon.cs @@ -37,8 +37,8 @@ namespace GWConquest { FormationImage.sprite = category.Icon; FormationNumberText.gameObject.SetActive(true); - FormationNumberText.text = f.formationNumber.ToString(); - FormationNumberEnding.text = Util.GetOrdinalEnding(f.formationNumber); + FormationNumberText.text = f.FormationNumber.ToString(); + FormationNumberEnding.text = Util.GetOrdinalEnding(f.FormationNumber); for(int i = 0; i < StrengthGameObjects.Length; i++) { diff --git a/Assets/GWConquest/Scripts/UI/GarrisonUI.cs b/Assets/GWConquest/Scripts/UI/GarrisonUI.cs index 11fc14b..03c0937 100644 --- a/Assets/GWConquest/Scripts/UI/GarrisonUI.cs +++ b/Assets/GWConquest/Scripts/UI/GarrisonUI.cs @@ -76,7 +76,7 @@ namespace GWConquest var icons = new List(); icons.AddRange(f.Units); - icons.AddRange(f.AllItems); + //icons.AddRange(f.AllItems); int unitsPerRow = Mathf.FloorToInt(armyGroupWidth / (unitWidth + IconOffset)); int rowCount = Mathf.CeilToInt((float)icons.Count / unitsPerRow); diff --git a/Assets/GWConquest/Scripts/UI/PlanetIndicatorUI.cs b/Assets/GWConquest/Scripts/UI/PlanetIndicatorUI.cs index 50c4eae..773e94a 100644 --- a/Assets/GWConquest/Scripts/UI/PlanetIndicatorUI.cs +++ b/Assets/GWConquest/Scripts/UI/PlanetIndicatorUI.cs @@ -67,6 +67,7 @@ namespace GWConquest EnemyIndicatorGround.SetActive(true); EnemyIndicatorBarGround.fillAmount = Mathf.Clamp01(enemyStrengthGround / MaxFormationStrength) * MaxFillAmount; + enemyPlayer = formationsGround.FirstOrDefault(f => f.Player != Player.CurrentPlayer)?.Player; if(enemyPlayer != null) { EnemyIndicatorBarGround.color = EnemyIndicatorBarGround.color.UpdateColorRGB(enemyPlayer.Color); @@ -82,7 +83,7 @@ namespace GWConquest } private void FixedUpdate() { - if(Planet != null) + if(GameManager.EntitiesLoaded && Planet != null) { var controllingPlayer = Planet.ControllingPlayer; diff --git a/Assets/GWConquest/Scripts/UI/TransportUIEquipmentIcon.cs b/Assets/GWConquest/Scripts/UI/TransportUIEquipmentIcon.cs index e21e741..05555ca 100644 --- a/Assets/GWConquest/Scripts/UI/TransportUIEquipmentIcon.cs +++ b/Assets/GWConquest/Scripts/UI/TransportUIEquipmentIcon.cs @@ -13,7 +13,7 @@ namespace GWConquest { Stack = stack; - if(stack != null) + if(stack.Amount > 0) { Icon.gameObject.SetActive(true); Icon.sprite = Stack.Icon; diff --git a/Assets/GWConquest/Scripts/UI/UnitInfoPanel.cs b/Assets/GWConquest/Scripts/UI/UnitInfoPanel.cs index aad623b..2628b8f 100644 --- a/Assets/GWConquest/Scripts/UI/UnitInfoPanel.cs +++ b/Assets/GWConquest/Scripts/UI/UnitInfoPanel.cs @@ -183,7 +183,7 @@ namespace GWConquest int equipmentCount = CurrentUnit.Equipment.Count; for(int i = 0; i < EquipmentIconList.Count; i++) { - var item = i < equipmentCount ? CurrentUnit.Equipment[i] : null; + var item = i < equipmentCount ? CurrentUnit.Equipment[i] : default(ItemStack); EquipmentIconList[i].UpdateDisplay(item); } } diff --git a/Assets/GWConquest/Scripts/Unit.cs b/Assets/GWConquest/Scripts/Unit.cs index 43aa356..b6ff1ba 100644 --- a/Assets/GWConquest/Scripts/Unit.cs +++ b/Assets/GWConquest/Scripts/Unit.cs @@ -241,6 +241,13 @@ namespace GWConquest } } + public override string ToString() + { + return Class.ShortName; + } + + + diff --git a/Assets/GWConquest/Scripts/Zone.cs b/Assets/GWConquest/Scripts/Zone.cs index adbbc7e..d4aed9a 100644 --- a/Assets/GWConquest/Scripts/Zone.cs +++ b/Assets/GWConquest/Scripts/Zone.cs @@ -21,11 +21,12 @@ namespace GWConquest [SerializeField] private int zoneId; - private List formations = new List(); - - public List Formations + public IEnumerable Formations { - get => formations; + //get => formations; + get { + return Formation.AllFormations.Where(f => f.State.CurrentZone == zoneId); + } } private static Dictionary zoneDict = new Dictionary(); @@ -84,7 +85,6 @@ namespace GWConquest public void OnFormationArrived(Formation formation) { - formations.Add(formation); OnFormationChanged(formation); if (BoltNetwork.IsServer) @@ -100,7 +100,7 @@ namespace GWConquest var battleEntity = BoltNetwork.Instantiate(BoltPrefabs.Battle); CurrentBattle = battleEntity.GetComponent(); CurrentBattle.Zone = this; - foreach (Formation f in formations) + foreach (Formation f in Formations) { CurrentBattle.AddFormation(f); } @@ -113,12 +113,11 @@ namespace GWConquest public bool ShouldStartBattle() { - return formations.Select((f, i) => f.Player).Distinct().Count() > 1; + return Formations.Select((f, i) => f.Player).Distinct().Count() > 1; } public void OnFormationDeparting(Formation formation) { - formations.Remove(formation); OnFormationChanged(formation); if (BoltNetwork.IsServer) diff --git a/Assets/Photon/PhotonBolt/assemblies/bolt.user.dll b/Assets/Photon/PhotonBolt/assemblies/bolt.user.dll index 8c7134d..0db92d1 100644 Binary files a/Assets/Photon/PhotonBolt/assemblies/bolt.user.dll and b/Assets/Photon/PhotonBolt/assemblies/bolt.user.dll differ diff --git a/Assets/Photon/PhotonBolt/assemblies/bolt.user.dll.mdb b/Assets/Photon/PhotonBolt/assemblies/bolt.user.dll.mdb index cf49b4f..4376ba6 100644 Binary files a/Assets/Photon/PhotonBolt/assemblies/bolt.user.dll.mdb and b/Assets/Photon/PhotonBolt/assemblies/bolt.user.dll.mdb differ diff --git a/Assets/Photon/PhotonBolt/project.json b/Assets/Photon/PhotonBolt/project.json index 24fe8e3..77eacd3 100644 --- a/Assets/Photon/PhotonBolt/project.json +++ b/Assets/Photon/PhotonBolt/project.json @@ -195,6 +195,24 @@ "SnapMagnitude": 10.0 } }, + { + "Name": "FormationNumber", + "Enabled": true, + "Expanded": true, + "ReplicationMode": 1, + "Priority": 1, + "PropertyType": { + "$type": "Bolt.Compiler.PropertyTypeInteger, bolt.compiler", + "MaxValue": 255 + }, + "AssetSettings": { + "$type": "Bolt.Compiler.PropertyStateSettings, bolt.compiler", + "ExtrapolationErrorTolerance": 0.25, + "_ExtrapolationCorrectionFrames": 6, + "ExtrapolationMaxFrames": 9, + "SnapMagnitude": 10.0 + } + }, { "Name": "MovementTargetFormation", "Enabled": true, @@ -1929,6 +1947,28 @@ "Name": "AssignLeaderEvent", "Guid": "19182fa7-e061-484b-8714-d5ddbdb8014b", "Groups": [] + }, + { + "$type": "Bolt.Compiler.EventDefinition, bolt.compiler", + "Properties": [ + { + "Name": "EntityCount", + "Enabled": true, + "Expanded": true, + "ReplicationMode": 1, + "Priority": 1, + "PropertyType": { + "$type": "Bolt.Compiler.PropertyTypeInteger, bolt.compiler", + "MaxValue": 255 + }, + "AssetSettings": { + "$type": "Bolt.Compiler.PropertyEventSettings, bolt.compiler" + } + } + ], + "Name": "ServerConfigEvent", + "Guid": "ee9e2713-bc29-4605-a500-6a6be50ae09c", + "Groups": [] } ], "ActiveGroup": "Everything" diff --git a/Assets/Photon/PhotonBolt/resources/BoltRuntimeSettings.asset b/Assets/Photon/PhotonBolt/resources/BoltRuntimeSettings.asset index bff8371..3c6e246 100644 --- a/Assets/Photon/PhotonBolt/resources/BoltRuntimeSettings.asset +++ b/Assets/Photon/PhotonBolt/resources/BoltRuntimeSettings.asset @@ -47,7 +47,7 @@ MonoBehaviour: debugClientCount: 1 debugStartPort: 50538 debugStartMapName: GalaxyMap - debugPlayAsServer: 1 + debugPlayAsServer: 0 showDebugInfo: 0 overrideTimeScale: 1 logUncaughtExceptions: 1