Feature/mirror upgrade (#127)

* Updated SyncDictionary usage in SyncedBag.cs

- Removed the extra class that is no longer needed for SyncDictionary's
- Removed OP codes (OP_DIRTY) switch case that no longer exists (superseded by OP_SET)

Signed-off-by: Lukas Olson <lukasolson@greyblockgames.com>

* Updated method names

Signed-off-by: Lukas Olson <lukasolson@greyblockgames.com>

* Updated more string sync dictionaries

Ped_Networking.cs
VehicleController.cs
Player.cs
SyncedServerData.cs

Signed-off-by: Lukas Olson <lukasolson@greyblockgames.com>

* Updated NetworkTime fields in NetStats.cs

Signed-off-by: Lukas Olson <lukasolson@greyblockgames.com>

* Updated syncData types

Signed-off-by: Lukas Olson <lukasolson@greyblockgames.com>

* Implemented conditional compilation to replace old isHeadless

Signed-off-by: Lukas Olson <lukasolson@greyblockgames.com>

* Updated hooks

* A few more syncDictionary upgrades

* Moved away from obsolete NetworkIdentity.spawned

* Updated SetDirtyBit to SetSyncVarDirtyBit in DeadBody.cs

* Updated ScriptingDefineSymbols for Mirror

* Updated JoinGameWindow.cs

* Use latest MirrorLite commit for submodule

* Use latest MirrorLite commit for submodule

* Reverted EditorSettings.asset to commit b1c9d38e3a

* Reverted JoinGameWindow.cs to commit b1c9d38e3a

* Changed method for headless mode in NetCmdLineHandler.cs

Changed from compiler defs to SanAndreasUnity helpers for determining headless mode in NetCmdLineHandler.cs

* Re-Added ConfigureHeadlessFrameRate override on CustomNetworkManager.cs

* Started updating JoinGameWindow.cs

- Commented out GUI errors
- Updated type 'DiscoveryInfo' to 'ServerResponse' in method ConnectFromDiscovery() params.
- Updated Connect() 'port' parameter to use type 'int' rather than 'ushort' as per Mirror conventions.

Co-authored-by: Lukas Olson <lukasolson@greyblockgames.com>
This commit is contained in:
Lukas 2022-04-02 11:15:08 -07:00 committed by GitHub
parent 42df0daa8c
commit 0445f29dfd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 178 additions and 151 deletions

@ -1 +1 @@
Subproject commit ee34eb4807d5d5d3b0121689acb286876633ffd1 Subproject commit 36591bb183cea0cb1c29f138fb5b226eca46f697

View file

@ -182,7 +182,7 @@ namespace SanAndreasUnity.Behaviours.Peds
public override void OnDeserialize(NetworkReader reader, bool initialState) public override void OnDeserialize(NetworkReader reader, bool initialState)
{ {
if (initialState) if (initialState)
m_net_modelId = reader.ReadInt32(); m_net_modelId = reader.ReadInt();
byte flags = reader.ReadByte(); byte flags = reader.ReadByte();
@ -254,7 +254,7 @@ namespace SanAndreasUnity.Behaviours.Peds
{ {
if (NetStatus.IsServer) if (NetStatus.IsServer)
{ {
this.SetDirtyBit(1); this.SetSyncVarDirtyBit(1);
} }
} }

View file

@ -32,11 +32,9 @@ namespace SanAndreasUnity.Behaviours
public static int NumStateChangesReceived { get; private set; } public static int NumStateChangesReceived { get; private set; }
public class SyncDictionaryStringUint : Mirror.SyncDictionary<string, uint> { } public readonly SyncDictionary<string, uint> syncDictionaryStringUint = new SyncDictionary<string, uint>();
public SyncDictionaryStringUint syncDictionaryStringUint = new SyncDictionaryStringUint(); private readonly SyncDictionary<string, string> _syncDictionary = new SyncDictionary<string, string>();
private SyncedBag.StringSyncDictionary _syncDictionary = new SyncedBag.StringSyncDictionary();
public SyncedBag SyncedBag { get; } public SyncedBag SyncedBag { get; }
[SyncVar] Vector3 m_net_movementInput; [SyncVar] Vector3 m_net_movementInput;
@ -189,7 +187,7 @@ namespace SanAndreasUnity.Behaviours
} }
void Net_OnIdChanged(int newId) void Net_OnIdChanged(int oldId, int newId)
{ {
//Debug.LogFormat("ped (net id {0}) changed model id to {1}", this.netId, newId); //Debug.LogFormat("ped (net id {0}) changed model id to {1}", this.netId, newId);
@ -199,7 +197,7 @@ namespace SanAndreasUnity.Behaviours
this.TryToLoadNewModel(newId); this.TryToLoadNewModel(newId);
} }
void Net_OnStateChanged(string newStateName) void Net_OnStateChanged(string oldStateName, string newStateName)
{ {
if (this.isServer) if (this.isServer)
return; return;
@ -241,7 +239,7 @@ namespace SanAndreasUnity.Behaviours
} }
void Net_OnWeaponChanged(int newSlot) void Net_OnWeaponChanged(int oldSlot, int newSlot)
{ {
if (NetStatus.IsServer) if (NetStatus.IsServer)
@ -261,7 +259,7 @@ namespace SanAndreasUnity.Behaviours
} }
void Net_OnMouthSoundIdChanged(Audio.SoundId newSoundId) void Net_OnMouthSoundIdChanged(Audio.SoundId oldSoundId, Audio.SoundId newSoundId)
{ {
if (NetStatus.IsServer) if (NetStatus.IsServer)
return; return;

View file

@ -1,3 +1,4 @@
using Mirror;
using UnityEngine; using UnityEngine;
using SanAndreasUnity.Utilities; using SanAndreasUnity.Utilities;
using SanAndreasUnity.Behaviours.Vehicles; using SanAndreasUnity.Behaviours.Vehicles;
@ -52,8 +53,8 @@ namespace SanAndreasUnity.Behaviours.Peds.States
// extract vehicle and seat from data // extract vehicle and seat from data
int magicNumber = reader.ReadInt32(); int magicNumber = reader.ReadInt();
m_currentVehicleNetId = reader.ReadUInt32(); m_currentVehicleNetId = reader.ReadUInt();
this.CurrentVehicleSeatAlignment = (Vehicle.SeatAlignment) reader.ReadSByte(); this.CurrentVehicleSeatAlignment = (Vehicle.SeatAlignment) reader.ReadSByte();
// assign current vehicle // assign current vehicle

View file

@ -1,3 +1,4 @@
using Mirror;
using UnityEngine; using UnityEngine;
using SanAndreasUnity.Utilities; using SanAndreasUnity.Utilities;
using SanAndreasUnity.Importing.Animation; using SanAndreasUnity.Importing.Animation;
@ -69,12 +70,12 @@ namespace SanAndreasUnity.Behaviours.Peds.States
string magicWord = reader.ReadString(); string magicWord = reader.ReadString();
if (magicWord != "roll") if (magicWord != "roll")
Debug.LogErrorFormat("wrong magic word when switching to roll state: {0}", magicWord); Debug.LogErrorFormat("wrong magic word when switching to roll state: {0}", magicWord);
m_rollLeft = reader.ReadBoolean(); m_rollLeft = reader.ReadBool();
m_ped.SwitchState(this.GetType()); m_ped.SwitchState(this.GetType());
} }
void OnDictChanged(Ped.SyncDictionaryStringUint.Operation op, string key, uint value) void OnDictChanged(SyncDictionary<string, uint>.Operation op, string key, uint value)
{ {
// switch (op) // switch (op)
// { // {

View file

@ -3,6 +3,7 @@ using SanAndreasUnity.Utilities;
using SanAndreasUnity.Behaviours.Vehicles; using SanAndreasUnity.Behaviours.Vehicles;
using SanAndreasUnity.Importing.Animation; using SanAndreasUnity.Importing.Animation;
using System.Linq; using System.Linq;
using Mirror;
namespace SanAndreasUnity.Behaviours.Peds.States namespace SanAndreasUnity.Behaviours.Peds.States
{ {

View file

@ -7,19 +7,26 @@ using System.Collections.Generic;
namespace SanAndreasUnity.Behaviours.Vehicles namespace SanAndreasUnity.Behaviours.Vehicles
{ {
public class VehicleController : NetworkBehaviour public class VehicleController : NetworkBehaviour
{ {
private Vehicle m_vehicle; private Vehicle m_vehicle;
bool IsControlledByLocalPlayer => m_vehicle.IsControlledByLocalPlayer; bool IsControlledByLocalPlayer => m_vehicle.IsControlledByLocalPlayer;
[SyncVar] int m_net_id; [SyncVar] int m_net_id;
[SyncVar(hook = nameof(OnNetColorsChanged))] string m_net_carColors;
[SyncVar(hook = nameof(OnNetColorsChanged))]
string m_net_carColors;
[SyncVar] float m_net_acceleration; [SyncVar] float m_net_acceleration;
[SyncVar] float m_net_steering; [SyncVar] float m_net_steering;
[SyncVar] float m_net_braking; [SyncVar] float m_net_braking;
[SyncVar(hook=nameof(OnNetPositionChanged))] Vector3 m_net_position;
[SyncVar(hook=nameof(OnNetRotationChanged))] Quaternion m_net_rotation; [SyncVar(hook = nameof(OnNetPositionChanged))]
Vector3 m_net_position;
[SyncVar(hook = nameof(OnNetRotationChanged))]
Quaternion m_net_rotation;
[SyncVar] Vector3 m_net_linearVelocity; [SyncVar] Vector3 m_net_linearVelocity;
[SyncVar] Vector3 m_net_angularVelocity; [SyncVar] Vector3 m_net_angularVelocity;
[SyncVar] float m_net_health; [SyncVar] float m_net_health;
@ -28,24 +35,24 @@ namespace SanAndreasUnity.Behaviours.Vehicles
{ {
public float brakeTorque; public float brakeTorque;
public float motorTorque; public float motorTorque;
public float steerAngle; public float steerAngle;
//public float travel; //public float travel;
public float localPosY; public float localPosY;
public float rpm; public float rpm;
} }
class WheelSyncList : SyncList<WheelSyncData> { }
WheelSyncList m_net_wheelsData = new WheelSyncList(); readonly SyncList<WheelSyncData> m_net_wheelsData = new SyncList<WheelSyncData>();
private readonly SyncedBag.StringSyncDictionary m_syncDictionary = new SyncedBag.StringSyncDictionary(); private readonly SyncDictionary<string, string> m_syncDictionary = new SyncDictionary<string, string>();
public SyncedBag ExtraData { get; } public SyncedBag ExtraData { get; }
// is it better to place syncvars in Vehicle class ? - that way, there is no need for hooks // is it better to place syncvars in Vehicle class ? - that way, there is no need for hooks
// - or we could assign/read syncvars in Update() // - or we could assign/read syncvars in Update()
private VehicleController() private VehicleController()
{ {
ExtraData = new SyncedBag(m_syncDictionary); ExtraData = new SyncedBag(m_syncDictionary);
@ -76,12 +83,14 @@ namespace SanAndreasUnity.Behaviours.Vehicles
if (!NetStatus.IsServer) if (!NetStatus.IsServer)
{ {
F.RunExceptionSafe( () => { F.RunExceptionSafe(() =>
{
// load vehicle on clients // load vehicle on clients
Color32[] colors = DeserializeColors(m_net_carColors); Color32[] colors = DeserializeColors(m_net_carColors);
m_vehicle = Vehicle.Create(this.gameObject, m_net_id, null, this.transform.position, this.transform.rotation); m_vehicle = Vehicle.Create(this.gameObject, m_net_id, null, this.transform.position,
this.transform.rotation);
m_vehicle.SetColors(colors); m_vehicle.SetColors(colors);
@ -136,7 +145,8 @@ namespace SanAndreasUnity.Behaviours.Vehicles
string[] splits = colorString.Split(';'); string[] splits = colorString.Split(';');
if (splits.Length != 4) if (splits.Length != 4)
throw new System.ArgumentException($"Failed to deserialize color - expected 4 components, found {splits.Length}"); throw new System.ArgumentException(
$"Failed to deserialize color - expected 4 components, found {splits.Length}");
return new Color32( return new Color32(
byte.Parse(splits[0], System.Globalization.CultureInfo.InvariantCulture), byte.Parse(splits[0], System.Globalization.CultureInfo.InvariantCulture),
@ -155,9 +165,8 @@ namespace SanAndreasUnity.Behaviours.Vehicles
private void Update() private void Update()
{ {
// if syncvars are used for updating transform, then disable NetworkTransform, and vice versa // if syncvars are used for updating transform, then disable NetworkTransform, and vice versa
m_vehicle.NetTransform.enabled = ! VehicleManager.Instance.syncVehicleTransformUsingSyncVars; m_vehicle.NetTransform.enabled = !VehicleManager.Instance.syncVehicleTransformUsingSyncVars;
// update status of rigid body // update status of rigid body
this.EnableOrDisableRigidBody(); this.EnableOrDisableRigidBody();
@ -203,7 +212,6 @@ namespace SanAndreasUnity.Behaviours.Vehicles
m_vehicle.Braking = oldBrake; m_vehicle.Braking = oldBrake;
m_vehicle.Steering = oldSteer; m_vehicle.Steering = oldSteer;
} }
} }
void ProcessSyncvars() void ProcessSyncvars()
@ -220,10 +228,13 @@ namespace SanAndreasUnity.Behaviours.Vehicles
m_net_health = m_vehicle.Health; m_net_health = m_vehicle.Health;
// wheels // wheels
m_net_wheelsData.Flush(); // remove current list of changes - this ensures that only the current wheel state is sent, and prevents memory leak bug in Mirror m_net_wheelsData
.ClearChanges(); // remove current list of changes - this ensures that only the current wheel state is sent, and prevents memory leak bug in Mirror
m_net_wheelsData.Clear(); m_net_wheelsData.Clear();
foreach (var wheel in m_vehicle.Wheels) { foreach (var wheel in m_vehicle.Wheels)
m_net_wheelsData.Add(new WheelSyncData() { {
m_net_wheelsData.Add(new WheelSyncData()
{
brakeTorque = wheel.Collider.brakeTorque, brakeTorque = wheel.Collider.brakeTorque,
motorTorque = wheel.Collider.motorTorque, motorTorque = wheel.Collider.motorTorque,
steerAngle = wheel.Collider.steerAngle, steerAngle = wheel.Collider.steerAngle,
@ -236,7 +247,8 @@ namespace SanAndreasUnity.Behaviours.Vehicles
else else
{ {
// apply input // apply input
if (!this.IsControlledByLocalPlayer || (this.IsControlledByLocalPlayer && !VehicleManager.Instance.controlInputOnLocalPlayer)) if (!this.IsControlledByLocalPlayer || (this.IsControlledByLocalPlayer &&
!VehicleManager.Instance.controlInputOnLocalPlayer))
{ {
m_vehicle.Accelerator = m_net_acceleration; m_vehicle.Accelerator = m_net_acceleration;
m_vehicle.Steering = m_net_steering; m_vehicle.Steering = m_net_steering;
@ -244,9 +256,11 @@ namespace SanAndreasUnity.Behaviours.Vehicles
} }
// update wheels // update wheels
if (!this.IsControlledByLocalPlayer || (this.IsControlledByLocalPlayer && !VehicleManager.Instance.controlWheelsOnLocalPlayer)) if (!this.IsControlledByLocalPlayer || (this.IsControlledByLocalPlayer &&
!VehicleManager.Instance.controlWheelsOnLocalPlayer))
{
for (int i = 0; i < m_vehicle.Wheels.Count && i < m_net_wheelsData.Count; i++)
{ {
for (int i=0; i < m_vehicle.Wheels.Count && i < m_net_wheelsData.Count; i++) {
var w = m_vehicle.Wheels[i]; var w = m_vehicle.Wheels[i];
var data = m_net_wheelsData[i]; var data = m_net_wheelsData[i];
@ -256,6 +270,7 @@ namespace SanAndreasUnity.Behaviours.Vehicles
w.Collider.motorTorque = data.motorTorque; w.Collider.motorTorque = data.motorTorque;
w.Collider.steerAngle = data.steerAngle; w.Collider.steerAngle = data.steerAngle;
} }
//w.Travel = data.travel; //w.Travel = data.travel;
w.Child.SetLocalY(data.localPosY); w.Child.SetLocalY(data.localPosY);
Vehicle.UpdateWheelRotation(w, data.rpm, data.steerAngle); Vehicle.UpdateWheelRotation(w, data.rpm, data.steerAngle);
@ -315,36 +330,38 @@ namespace SanAndreasUnity.Behaviours.Vehicles
return; return;
} }
if (VehicleManager.Instance.whenToDisableRigidBody.Matches(this.IsControlledByLocalPlayer, !NetStatus.IsServer)) if (VehicleManager.Instance.whenToDisableRigidBody.Matches(this.IsControlledByLocalPlayer,
!NetStatus.IsServer))
F.DisableRigidBody(m_vehicle.RigidBody); F.DisableRigidBody(m_vehicle.RigidBody);
else else
F.EnableRigidBody(m_vehicle.RigidBody); F.EnableRigidBody(m_vehicle.RigidBody);
} }
void OnNetPositionChanged(Vector3 pos) void OnNetPositionChanged(Vector3 oldPos, Vector3 newPos)
{ {
if (NetStatus.IsServer) if (NetStatus.IsServer)
return; return;
if (VehicleManager.Instance.syncVehicleTransformUsingSyncVars) { if (VehicleManager.Instance.syncVehicleTransformUsingSyncVars)
{
if (m_vehicle != null && m_vehicle.RigidBody != null) if (m_vehicle != null && m_vehicle.RigidBody != null)
m_vehicle.RigidBody.MovePosition(pos); m_vehicle.RigidBody.MovePosition(newPos);
} }
} }
void OnNetRotationChanged(Quaternion rot) void OnNetRotationChanged(Quaternion oldRot, Quaternion newRot)
{ {
if (NetStatus.IsServer) if (NetStatus.IsServer)
return; return;
if (VehicleManager.Instance.syncVehicleTransformUsingSyncVars) { if (VehicleManager.Instance.syncVehicleTransformUsingSyncVars)
{
if (m_vehicle != null && m_vehicle.RigidBody != null) if (m_vehicle != null && m_vehicle.RigidBody != null)
m_vehicle.RigidBody.MoveRotation(rot); m_vehicle.RigidBody.MoveRotation(newRot);
} }
} }
void OnNetColorsChanged(string stringColors) void OnNetColorsChanged(string oldColors, string stringColors)
{ {
if (NetStatus.IsServer) if (NetStatus.IsServer)
return; return;
@ -352,6 +369,5 @@ namespace SanAndreasUnity.Behaviours.Vehicles
if (m_vehicle != null) if (m_vehicle != null)
F.RunExceptionSafe(() => m_vehicle.SetColors(DeserializeColors(stringColors))); F.RunExceptionSafe(() => m_vehicle.SetColors(DeserializeColors(stringColors)));
} }
} }
} }

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using Mirror; using Mirror;
@ -6,42 +7,38 @@ using SanAndreasUnity.Behaviours;
namespace SanAndreasUnity.Net namespace SanAndreasUnity.Net
{ {
public class CustomNetworkManager : NetworkManager public class CustomNetworkManager : NetworkManager
{ {
public override void OnClientConnect()
public override void OnClientConnect(NetworkConnection conn)
{ {
if (NetStatus.IsServer) if (NetStatus.IsServer)
{ {
// just do default action // just do default action
base.OnClientConnect(conn); base.OnClientConnect();
return; return;
} }
// default method: if no scene was loaded, do Ready/AddPlayer // default method: if no scene was loaded, do Ready/AddPlayer
// we won't do this until loading process finishes // we won't do this until loading process finishes
if (Loader.HasLoaded) if (Loader.HasLoaded)
base.OnClientConnect(conn); base.OnClientConnect();
} }
public override void OnClientSceneChanged(NetworkConnection conn) public override void OnClientSceneChanged()
{ {
if (NetStatus.IsServer) if (NetStatus.IsServer)
{ {
// just do default action // just do default action
base.OnClientSceneChanged(conn); base.OnClientSceneChanged();
return; return;
} }
// default method: do Ready/AddPlayer // default method: do Ready/AddPlayer
// we won't do this until loading process finishes // we won't do this until loading process finishes
if (Loader.HasLoaded) if (Loader.HasLoaded)
base.OnClientSceneChanged(conn); base.OnClientSceneChanged();
} }
void OnLoaderFinished() void OnLoaderFinished()
@ -59,26 +56,25 @@ namespace SanAndreasUnity.Net
return; return;
} }
// make client ready // make client ready
if (ClientScene.ready) if (NetworkClient.ready)
Debug.LogErrorFormat("Client was made ready before loader finished"); Debug.LogErrorFormat("Client was made ready before loader finished");
else else
ClientScene.Ready(NetworkClient.connection); {
NetworkClient.Ready();
}
// add player if specified // add player if specified
if (autoCreatePlayer && ClientScene.localPlayer == null) if (autoCreatePlayer && NetworkClient.localPlayer == null)
{ {
ClientScene.AddPlayer(); NetworkClient.AddPlayer();
} }
} }
public override void ConfigureServerFrameRate() public override void ConfigureHeadlessFrameRate()
{ {
// don't set frame rate //Overriden so that other scripts can set the framerate without Mirror overriding it.
// it will be done by other scripts
} }
} }
} }

View file

@ -8,25 +8,28 @@ namespace SanAndreasUnity.Net
{ {
public class NetCmdLineHandler : MonoBehaviour public class NetCmdLineHandler : MonoBehaviour
{ {
public int numFramesToWait = 5; public int numFramesToWait = 5;
IEnumerator Start() IEnumerator Start()
{ {
if (!Mirror.NetworkManager.isHeadless) if (F.IsInHeadlessMode)
{
yield break; yield break;
}
for (int i=0; i < this.numFramesToWait; i++)
for (int i = 0; i < this.numFramesToWait; i++)
yield return null; yield return null;
ushort portNum = (ushort) NetManager.defaultListenPortNumber; ushort portNum = (ushort)NetManager.defaultListenPortNumber;
CmdLineUtils.GetUshortArgument("portNum", ref portNum); CmdLineUtils.GetUshortArgument("portNum", ref portNum);
string sceneName = "Main"; string sceneName = "Main";
CmdLineUtils.GetArgument("scene", ref sceneName); CmdLineUtils.GetArgument("scene", ref sceneName);
ushort maxNumPlayers = (ushort) NetManager.maxNumPlayers; ushort maxNumPlayers = (ushort)NetManager.maxNumPlayers;
CmdLineUtils.GetUshortArgument("maxNumPlayers", ref maxNumPlayers); CmdLineUtils.GetUshortArgument("maxNumPlayers", ref maxNumPlayers);
string serverIp = "127.0.0.1"; string serverIp = "127.0.0.1";
@ -45,7 +48,8 @@ namespace SanAndreasUnity.Net
if (CmdLineUtils.HasArgument("startServer")) if (CmdLineUtils.HasArgument("startServer"))
{ {
Debug.LogFormat("Starting server in headless mode, params: {0}, {1}, {2}", portNum, sceneName, maxNumPlayers); Debug.LogFormat("Starting server in headless mode, params: {0}, {1}, {2}", portNum, sceneName,
maxNumPlayers);
NetManager.StartServer(portNum, sceneName, maxNumPlayers, true, false); NetManager.StartServer(portNum, sceneName, maxNumPlayers, true, false);
} }
else if (CmdLineUtils.HasArgument("startClient")) else if (CmdLineUtils.HasArgument("startClient"))
@ -53,10 +57,6 @@ namespace SanAndreasUnity.Net
Debug.LogFormat("Starting client in headless mode, params: {0}, {1}", serverIp, portNum); Debug.LogFormat("Starting client in headless mode, params: {0}, {1}", serverIp, portNum);
NetManager.StartClient(serverIp, portNum); NetManager.StartClient(serverIp, portNum);
} }
} }
} }
} }

View file

@ -1,4 +1,6 @@
using UnityEngine; using System;
using System.Collections.Generic;
using UnityEngine;
using Mirror; using Mirror;
using SanAndreasUnity.Utilities; using SanAndreasUnity.Utilities;
@ -37,7 +39,27 @@ namespace SanAndreasUnity.Net
private NetworkServerStatus m_lastServerStatus = NetworkServerStatus.Stopped; private NetworkServerStatus m_lastServerStatus = NetworkServerStatus.Stopped;
public event System.Action onServerStatusChanged = delegate {}; public event System.Action onServerStatusChanged = delegate {};
public static int NumSpawnedNetworkObjects => NetworkIdentity.spawned.Count;
public static Dictionary<uint, NetworkIdentity> ActiveSpawnedList
{
get
{
if (NetworkServer.active)
{
return NetworkServer.spawned;
}
else if (NetworkClient.active)
{
return NetworkClient.spawned;
}
throw new Exception(
"NetManager.ActiveSpawnedList was accessed before NetworkServer/NetworkClient were active.");
}
}
public static int NumSpawnedNetworkObjects => ActiveSpawnedList.Count;
public static double NetworkTime => Mirror.NetworkTime.time; public static double NetworkTime => Mirror.NetworkTime.time;
@ -231,12 +253,12 @@ namespace SanAndreasUnity.Net
var netIdentity = go.GetComponentOrThrow<NetworkIdentity>(); var netIdentity = go.GetComponentOrThrow<NetworkIdentity>();
if (netIdentity.clientAuthorityOwner == player.connectionToClient) // already has authority if (netIdentity.connectionToClient == player.connectionToClient) // already has authority
return; return;
// first remove existing authority client // first remove existing authority client
if (netIdentity.clientAuthorityOwner != null) if (netIdentity.connectionToClient != null)
netIdentity.RemoveClientAuthority(netIdentity.clientAuthorityOwner); netIdentity.RemoveClientAuthority();
// assign new authority client // assign new authority client
netIdentity.AssignClientAuthority(player.connectionToClient); netIdentity.AssignClientAuthority(player.connectionToClient);
@ -249,8 +271,8 @@ namespace SanAndreasUnity.Net
var netIdentity = go.GetComponentOrThrow<NetworkIdentity>(); var netIdentity = go.GetComponentOrThrow<NetworkIdentity>();
if (netIdentity.clientAuthorityOwner != null) if (netIdentity.connectionToClient != null)
netIdentity.RemoveClientAuthority(netIdentity.clientAuthorityOwner); netIdentity.RemoveClientAuthority();
} }
@ -261,13 +283,8 @@ namespace SanAndreasUnity.Net
public static GameObject GetNetworkObjectById(uint netId) public static GameObject GetNetworkObjectById(uint netId)
{ {
NetworkIdentity networkIdentity; if (!ActiveSpawnedList.TryGetValue(netId, out var networkIdentity)) return null;
if (NetworkIdentity.spawned.TryGetValue(netId, out networkIdentity)) return networkIdentity != null ? networkIdentity.gameObject : null;
{
if (networkIdentity != null)
return networkIdentity.gameObject;
}
return null;
} }
} }

View file

@ -129,7 +129,7 @@ namespace SanAndreasUnity.Net
this.UpdateClient(); this.UpdateClient();
} }
void OnNetPositionChanged(Vector3 pos) void OnNetPositionChanged(Vector3 oldPos, Vector3 newPos)
{ {
if (NetStatus.IsServer) if (NetStatus.IsServer)
return; return;
@ -137,10 +137,10 @@ namespace SanAndreasUnity.Net
if (null == this.Rigidbody) if (null == this.Rigidbody)
return; return;
this.Rigidbody.MovePosition(pos); this.Rigidbody.MovePosition(newPos);
} }
void OnNetRotationChanged(Vector3 eulers) void OnNetRotationChanged(Vector3 oldEulers, Vector3 newEulers)
{ {
if (NetStatus.IsServer) if (NetStatus.IsServer)
return; return;
@ -148,7 +148,7 @@ namespace SanAndreasUnity.Net
if (null == this.Rigidbody) if (null == this.Rigidbody)
return; return;
this.Rigidbody.MoveRotation(Quaternion.Euler(eulers)); this.Rigidbody.MoveRotation(Quaternion.Euler(newEulers));
} }
} }

View file

@ -43,7 +43,7 @@ namespace SanAndreasUnity.Net
public string DescriptionForLogging => "(netId=" + this.netId + ", addr=" + (this.connectionToClient != null ? this.connectionToClient.address : "") + ")"; public string DescriptionForLogging => "(netId=" + this.netId + ", addr=" + (this.connectionToClient != null ? this.connectionToClient.address : "") + ")";
private readonly SyncedBag.StringSyncDictionary m_syncDictionary = new SyncedBag.StringSyncDictionary(); private readonly SyncDictionary<string, string> m_syncDictionary = new SyncDictionary<string, string>();
public SyncedBag ExtraData { get; } public SyncedBag ExtraData { get; }
@ -113,16 +113,16 @@ namespace SanAndreasUnity.Net
F.InvokeEventExceptionSafe(onStart, this); F.InvokeEventExceptionSafe(onStart, this);
} }
public override void OnNetworkDestroy() public override void OnStopClient()
{ {
base.OnNetworkDestroy(); base.OnStopClient();
// log some info about this // log some info about this
if (!this.isLocalPlayer) if (!this.isLocalPlayer)
Debug.LogFormat("Player {0} disconnected, time: {1}", this.DescriptionForLogging, F.CurrentDateForLogging); Debug.LogFormat("Player {0} disconnected, time: {1}", this.DescriptionForLogging, F.CurrentDateForLogging);
} }
void OnOwnedGameObjectChanged(GameObject newGo) void OnOwnedGameObjectChanged(GameObject oldGo, GameObject newGo)
{ {
Debug.LogFormat("Owned game object changed for player (net id {0})", this.netId); Debug.LogFormat("Owned game object changed for player (net id {0})", this.netId);

View file

@ -9,12 +9,10 @@ namespace SanAndreasUnity.Net
{ {
public class SyncedBag public class SyncedBag
{ {
public class StringSyncDictionary : SyncDictionary<string, string> private readonly SyncDictionary<string, string> m_syncDictionary;
{
}
private readonly StringSyncDictionary m_syncDictionary; private readonly Dictionary<string, List<System.Action<string>>> m_callbacks =
private readonly Dictionary<string, List<System.Action<string>>> m_callbacks = new Dictionary<string, List<Action<string>>>(); new Dictionary<string, List<Action<string>>>();
private struct ArrayWrapper<T> // use struct so that it doesn't allocate memory private struct ArrayWrapper<T> // use struct so that it doesn't allocate memory
{ {
@ -27,24 +25,22 @@ namespace SanAndreasUnity.Net
} }
public SyncedBag(StringSyncDictionary syncDictionary) public SyncedBag(SyncDictionary<string, string> syncDictionary)
{ {
m_syncDictionary = syncDictionary; m_syncDictionary = syncDictionary;
m_syncDictionary.Callback += DictionaryCallback; m_syncDictionary.Callback += DictionaryCallback;
} }
private void DictionaryCallback(StringSyncDictionary.Operation op, string key, string item) private void DictionaryCallback(SyncDictionary<string, string>.Operation op, string key, string item)
{ {
if (NetUtils.IsServer) if (NetUtils.IsServer)
return; return;
switch (op) switch (op)
{ {
case StringSyncDictionary.Operation.OP_ADD: case SyncDictionary<string, string>.Operation.OP_ADD:
case StringSyncDictionary.Operation.OP_SET: case SyncDictionary<string, string>.Operation.OP_SET:
case StringSyncDictionary.Operation.OP_DIRTY:
if (m_callbacks.TryGetValue(key, out var list)) if (m_callbacks.TryGetValue(key, out var list))
{ {
// don't leave garbage // don't leave garbage
@ -67,7 +63,7 @@ namespace SanAndreasUnity.Net
} }
else else
{ {
m_callbacks.Add(key, new List<Action<string>>{callback}); m_callbacks.Add(key, new List<Action<string>> { callback });
} }
} }

View file

@ -8,9 +8,9 @@ namespace SanAndreasUnity.Net
{ {
public static SyncedServerData Instance { get; private set; } public static SyncedServerData Instance { get; private set; }
SyncedBag.StringSyncDictionary _syncDictionary = new SyncedBag.StringSyncDictionary(); readonly SyncDictionary<string, string> _syncDictionary = new SyncDictionary<string, string>();
public static SyncedBag Data { get; private set; } = new SyncedBag(new SyncedBag.StringSyncDictionary()); public static SyncedBag Data { get; private set; } = new SyncedBag(new SyncDictionary<string, string>());
public static event System.Action onInitialSyncDataAvailable = delegate {}; public static event System.Action onInitialSyncDataAvailable = delegate {};
@ -49,7 +49,7 @@ namespace SanAndreasUnity.Net
private void OnDisable() private void OnDisable()
{ {
// clear data for next server start // clear data for next server start
Data = new SyncedBag(new SyncedBag.StringSyncDictionary()); Data = new SyncedBag(new SyncDictionary<string, string>());
} }
public override void OnStartClient() public override void OnStartClient()

View file

@ -1,4 +1,3 @@
using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using Mirror; using Mirror;
@ -9,15 +8,13 @@ namespace SanAndreasUnity.Stats
{ {
public class NetStats : MonoBehaviour public class NetStats : MonoBehaviour
{ {
void Start() void Start()
{ {
Utilities.Stats.RegisterStat(new Utilities.Stats.Entry(){category = "NET", onGUI = OnStatGUI}); Utilities.Stats.RegisterStat(new Utilities.Stats.Entry() { category = "NET", onGUI = OnStatGUI });
} }
void OnStatGUI() void OnStatGUI()
{ {
GUILayout.Label("Time: " + NetworkTime.time); GUILayout.Label("Time: " + NetworkTime.time);
if (NetStatus.IsServer) if (NetStatus.IsServer)
@ -33,15 +30,14 @@ namespace SanAndreasUnity.Stats
Utilities.GUIUtils.DrawHorizontalLine(1, 1, Color.black); Utilities.GUIUtils.DrawHorizontalLine(1, 1, Color.black);
GUILayout.Label("Ping: " + NetworkTime.rtt); GUILayout.Label("Ping: " + NetworkTime.rtt);
GUILayout.Label("Ping send frequency: " + NetworkTime.PingFrequency); GUILayout.Label("Ping send frequency: " + NetworkTime.PingFrequency);
GUILayout.Label("Rtt sd: " + NetworkTime.rttSd); GUILayout.Label("Rtt sd: " + NetworkTime.rttStandardDeviation);
GUILayout.Label("Rtt var: " + NetworkTime.rttVar); GUILayout.Label("Rtt var: " + NetworkTime.rttVariance);
GUILayout.Label("Server ip: " + NetworkClient.serverIp); GUILayout.Label("Server ip: " + NetworkClient.serverIp);
GUILayout.Label("Time since last message: " + (Time.unscaledTime - NetworkClient.connection.lastMessageTime)); GUILayout.Label("Time since last message: " +
(Time.unscaledTime - NetworkClient.connection.lastMessageTime));
} }
GUILayout.Label($"Num spawned network objects: {NetManager.NumSpawnedNetworkObjects}"); GUILayout.Label($"Num spawned network objects: {NetManager.NumSpawnedNetworkObjects}");
} }
} }
} }

View file

@ -4,6 +4,7 @@ using SanAndreasUnity.Utilities;
using SanAndreasUnity.Net; using SanAndreasUnity.Net;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Mirror.Discovery;
namespace SanAndreasUnity.UI namespace SanAndreasUnity.UI
{ {
@ -18,7 +19,7 @@ namespace SanAndreasUnity.UI
int m_currentTabIndex = InternetTabIndex; int m_currentTabIndex = InternetTabIndex;
Mirror.NetworkDiscoveryHUD m_netDiscoveryHUD; NetworkDiscoveryHUD m_netDiscoveryHUD;
private List<ServerInfo> _serversFromMasterServer = new List<ServerInfo>(); private List<ServerInfo> _serversFromMasterServer = new List<ServerInfo>();
private Vector2 _masterServerScrollViewPos; private Vector2 _masterServerScrollViewPos;
@ -44,9 +45,11 @@ namespace SanAndreasUnity.UI
float height = width * 9f / 16f; float height = width * 9f / 16f;
this.windowRect = GUIUtils.GetCenteredRect(new Vector2(width, height)); this.windowRect = GUIUtils.GetCenteredRect(new Vector2(width, height));
m_netDiscoveryHUD = Mirror.NetworkManager.singleton.GetComponentOrThrow<Mirror.NetworkDiscoveryHUD>(); m_netDiscoveryHUD = Mirror.NetworkManager.singleton.GetComponentOrThrow<NetworkDiscoveryHUD>();
m_netDiscoveryHUD.connectAction = this.ConnectFromDiscovery;
m_netDiscoveryHUD.drawGUI = false; // TODO: NetworkDiscoveryHud connection actions & draw gui
// m_netDiscoveryHUD.connectAction = this.ConnectFromDiscovery;
// m_netDiscoveryHUD.drawGUI = false;
} }
void Update() void Update()
@ -85,8 +88,9 @@ namespace SanAndreasUnity.UI
} }
else if (LanTabIndex == m_currentTabIndex) else if (LanTabIndex == m_currentTabIndex)
{ {
m_netDiscoveryHUD.width = (int) this.WindowSize.x - 30; //TODO: NetDiscovery Hud window resizing
m_netDiscoveryHUD.DisplayServers(); //m_netDiscoveryHUD.width = (int) this.WindowSize.x - 30;
//m_netDiscoveryHUD.DisplayServers();
} }
else if (InternetTabIndex == m_currentTabIndex) else if (InternetTabIndex == m_currentTabIndex)
{ {
@ -161,9 +165,10 @@ namespace SanAndreasUnity.UI
{ {
if (LanTabIndex == m_currentTabIndex) if (LanTabIndex == m_currentTabIndex)
{ {
GUI.enabled = ! m_netDiscoveryHUD.IsRefreshing; //TODO: NetDiscovery Hud visibility & button stuff
buttonText = m_netDiscoveryHUD.IsRefreshing ? ( "Refreshing." + new string('.', (int) ((Time.time * 2) % 3)) ) : "Refresh LAN"; // GUI.enabled = ! m_netDiscoveryHUD.IsRefreshing;
buttonAction = () => m_netDiscoveryHUD.Refresh(); // buttonText = m_netDiscoveryHUD.IsRefreshing ? ( "Refreshing." + new string('.', (int) ((Time.time * 2) % 3)) ) : "Refresh LAN";
// buttonAction = () => m_netDiscoveryHUD.Refresh();
} }
else if (InternetTabIndex == m_currentTabIndex) else if (InternetTabIndex == m_currentTabIndex)
{ {
@ -203,20 +208,20 @@ namespace SanAndreasUnity.UI
void ConnectDirectly() void ConnectDirectly()
{ {
this.Connect(m_ipStr, ushort.Parse(m_portStr)); this.Connect(m_ipStr, int.Parse(m_portStr));
} }
void ConnectFromDiscovery(Mirror.NetworkDiscovery.DiscoveryInfo info) void ConnectFromDiscovery(ServerResponse info)
{ {
this.Connect(info.EndPoint.Address.ToString(), ushort.Parse( info.KeyValuePairs[Mirror.NetworkDiscovery.kPortKey] )); this.Connect(info.EndPoint.Address.ToString(), info.EndPoint.Port);
} }
void ConnectToServerFromMasterServer(ServerInfo serverInfo) void ConnectToServerFromMasterServer(ServerInfo serverInfo)
{ {
Connect(serverInfo.IP, (ushort) serverInfo.Port); Connect(serverInfo.IP, serverInfo.Port);
} }
void Connect(string ip, ushort port) void Connect(string ip, int port)
{ {
try try
{ {

View file

@ -677,7 +677,7 @@ PlayerSettings:
webGLThreadsSupport: 0 webGLThreadsSupport: 0
webGLDecompressionFallback: 0 webGLDecompressionFallback: 0
scriptingDefineSymbols: scriptingDefineSymbols:
1: CLIENT1;UNITY_POST_PROCESSING_STACK_V2;MIRROR;MIRROR_1726_OR_NEWER;MIRROR_3_0_OR_NEWER 1: CLIENT1;UNITY_POST_PROCESSING_STACK_V2;MIRROR;MIRROR_1726_OR_NEWER;MIRROR_3_0_OR_NEWER;MIRROR_17_0_OR_NEWER;MIRROR_18_0_OR_NEWER;MIRROR_24_0_OR_NEWER;MIRROR_26_0_OR_NEWER;MIRROR_27_0_OR_NEWER;MIRROR_28_0_OR_NEWER;MIRROR_29_0_OR_NEWER;MIRROR_30_0_OR_NEWER;MIRROR_30_5_2_OR_NEWER;MIRROR_32_1_2_OR_NEWER;MIRROR_32_1_4_OR_NEWER;MIRROR_35_0_OR_NEWER;MIRROR_35_1_OR_NEWER;MIRROR_37_0_OR_NEWER;MIRROR_38_0_OR_NEWER;MIRROR_39_0_OR_NEWER;MIRROR_40_0_OR_NEWER;MIRROR_41_0_OR_NEWER;MIRROR_42_0_OR_NEWER;MIRROR_43_0_OR_NEWER;MIRROR_44_0_OR_NEWER;MIRROR_46_0_OR_NEWER;MIRROR_47_0_OR_NEWER;MIRROR_53_0_OR_NEWER;MIRROR_55_0_OR_NEWER;MIRROR_57_0_OR_NEWER;MIRROR_58_0_OR_NEWER;MIRROR_65_0_OR_NEWER
4: UNITY_POST_PROCESSING_STACK_V2 4: UNITY_POST_PROCESSING_STACK_V2
7: CLIENT1;UNITY_POST_PROCESSING_STACK_V2;MIRROR;MIRROR_1726_OR_NEWER;MIRROR_3_0_OR_NEWER 7: CLIENT1;UNITY_POST_PROCESSING_STACK_V2;MIRROR;MIRROR_1726_OR_NEWER;MIRROR_3_0_OR_NEWER
13: UNITY_POST_PROCESSING_STACK_V2 13: UNITY_POST_PROCESSING_STACK_V2