diff --git a/LICENSE b/LICENSE
index 4f7b837..f3d1d29 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2019 MichalPetryka
+Copyright (c) 2019 - 2020 MichalPetryka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/ConnectionRequest.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/ConnectionRequest.cs
index 8bdbc7d..2ae99e3 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/ConnectionRequest.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/ConnectionRequest.cs
@@ -14,45 +14,49 @@ internal enum ConnectionRequestResult
{
None,
Accept,
- Reject
- }
-
- internal interface IConnectionRequestListener
- {
- void OnConnectionSolved(ConnectionRequest request, byte[] rejectData, int start, int length);
+ Reject,
+ RejectForce
}
public class ConnectionRequest
{
- private readonly IConnectionRequestListener _listener;
+ private readonly NetManager _listener;
private int _used;
- public IPEndPoint RemoteEndPoint { get { return Peer.EndPoint; } }
public readonly NetDataReader Data;
public ConnectionRequestType Type { get; private set; }
internal ConnectionRequestResult Result { get; private set; }
- internal readonly long ConnectionId;
- internal readonly byte ConnectionNumber;
- internal readonly NetPeer Peer;
+ internal long ConnectionTime;
+ internal byte ConnectionNumber;
+ public readonly IPEndPoint RemoteEndPoint;
private bool TryActivate()
{
return Interlocked.CompareExchange(ref _used, 1, 0) == 0;
}
+ internal void UpdateRequest(NetConnectRequestPacket connRequest)
+ {
+ if (connRequest.ConnectionTime >= ConnectionTime)
+ {
+ ConnectionTime = connRequest.ConnectionTime;
+ ConnectionNumber = connRequest.ConnectionNumber;
+ }
+ }
+
internal ConnectionRequest(
long connectionId,
byte connectionNumber,
ConnectionRequestType type,
NetDataReader netDataReader,
- NetPeer peer,
- IConnectionRequestListener listener)
+ IPEndPoint endPoint,
+ NetManager listener)
{
- ConnectionId = connectionId;
+ ConnectionTime = connectionId;
ConnectionNumber = connectionNumber;
Type = type;
- Peer = peer;
+ RemoteEndPoint = endPoint;
Data = netDataReader;
_listener = listener;
}
@@ -64,16 +68,15 @@ public NetPeer AcceptIfKey(string key)
try
{
if (Data.GetString() == key)
- {
Result = ConnectionRequestResult.Accept;
- _listener.OnConnectionSolved(this, null, 0, 0);
- return Peer;
- }
}
catch
{
NetDebug.WriteError("[AC] Invalid incoming data");
}
+ if (Result == ConnectionRequestResult.Accept)
+ return _listener.OnConnectionSolved(this, null, 0, 0);
+
Result = ConnectionRequestResult.Reject;
_listener.OnConnectionSolved(this, null, 0, 0);
return null;
@@ -88,31 +91,56 @@ public NetPeer Accept()
if (!TryActivate())
return null;
Result = ConnectionRequestResult.Accept;
- _listener.OnConnectionSolved(this, null, 0, 0);
- return Peer;
+ return _listener.OnConnectionSolved(this, null, 0, 0);
}
-
- public void Reject(byte[] rejectData, int start, int length)
+
+ public void Reject(byte[] rejectData, int start, int length, bool force)
{
if (!TryActivate())
return;
- Result = ConnectionRequestResult.Reject;
+ Result = force ? ConnectionRequestResult.RejectForce : ConnectionRequestResult.Reject;
_listener.OnConnectionSolved(this, rejectData, start, length);
}
+ public void Reject(byte[] rejectData, int start, int length)
+ {
+ Reject(rejectData, start, length, false);
+ }
+
+
+ public void RejectForce(byte[] rejectData, int start, int length)
+ {
+ Reject(rejectData, start, length, true);
+ }
+
+ public void RejectForce()
+ {
+ Reject(null, 0, 0, true);
+ }
+
+ public void RejectForce(byte[] rejectData)
+ {
+ Reject(rejectData, 0, rejectData.Length, true);
+ }
+
+ public void RejectForce(NetDataWriter rejectData)
+ {
+ Reject(rejectData.Data, 0, rejectData.Length, true);
+ }
+
public void Reject()
{
- Reject(null, 0, 0);
+ Reject(null, 0, 0, false);
}
public void Reject(byte[] rejectData)
{
- Reject(rejectData, 0, rejectData.Length);
+ Reject(rejectData, 0, rejectData.Length, false);
}
public void Reject(NetDataWriter rejectData)
{
- Reject(rejectData.Data, 0, rejectData.Length);
+ Reject(rejectData.Data, 0, rejectData.Length, false);
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/INetEventListener.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/INetEventListener.cs
index 1ebe5b0..e793127 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/INetEventListener.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/INetEventListener.cs
@@ -25,7 +25,8 @@ public enum DisconnectReason
DisconnectPeerCalled,
ConnectionRejected,
InvalidProtocol,
- UnknownHost
+ UnknownHost,
+ Reconnect
}
///
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples.meta b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers.meta
similarity index 77%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples.meta
rename to LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers.meta
index b594a81..fe3d455 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples.meta
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: a08b1f591326642d1b140fc818c9c6b1
+guid: edd8ad3518523b34688804a997e701da
folderAsset: yes
DefaultImporter:
externalObjects: {}
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/Crc32cLayer.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/Crc32cLayer.cs
new file mode 100644
index 0000000..716c4b5
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/Crc32cLayer.cs
@@ -0,0 +1,36 @@
+using LiteNetLib.Utils;
+using System;
+
+namespace LiteNetLib.Layers
+{
+ public sealed class Crc32cLayer : PacketLayerBase
+ {
+ public Crc32cLayer() : base(CRC32C.ChecksumSize)
+ {
+
+ }
+
+ public override void ProcessInboundPacket(ref byte[] data, ref int length)
+ {
+ if (length < NetConstants.HeaderSize + CRC32C.ChecksumSize)
+ {
+ NetDebug.WriteError("[NM] DataReceived size: bad!");
+ return;
+ }
+
+ int checksumPoint = length - CRC32C.ChecksumSize;
+ if (CRC32C.Compute(data, 0, checksumPoint) != BitConverter.ToUInt32(data, checksumPoint))
+ {
+ NetDebug.Write("[NM] DataReceived checksum: bad!");
+ return;
+ }
+ length -= CRC32C.ChecksumSize;
+ }
+
+ public override void ProcessOutBoundPacket(ref byte[] data, ref int offset, ref int length)
+ {
+ FastBitConverter.GetBytes(data, length, CRC32C.Compute(data, offset, length));
+ length += CRC32C.ChecksumSize;
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkIdentityEditor.cs.meta b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/Crc32cLayer.cs.meta
similarity index 83%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkIdentityEditor.cs.meta
rename to LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/Crc32cLayer.cs.meta
index cb4a5cf..4f9abaa 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkIdentityEditor.cs.meta
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/Crc32cLayer.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 1b6e3680cc14b4769bff378e5dbc3544
+guid: cbf352100f996cd4a989cfa47f660ded
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/PacketLayerBase.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/PacketLayerBase.cs
new file mode 100644
index 0000000..264a418
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/PacketLayerBase.cs
@@ -0,0 +1,15 @@
+namespace LiteNetLib.Layers
+{
+ public abstract class PacketLayerBase
+ {
+ public readonly int ExtraPacketSizeForLayer;
+
+ protected PacketLayerBase(int extraPacketSizeForLayer)
+ {
+ ExtraPacketSizeForLayer = extraPacketSizeForLayer;
+ }
+
+ public abstract void ProcessInboundPacket(ref byte[] data, ref int length);
+ public abstract void ProcessOutBoundPacket(ref byte[] data, ref int offset, ref int length);
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/SimpleChannel.cs.meta b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/PacketLayerBase.cs.meta
similarity index 83%
rename from LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/SimpleChannel.cs.meta
rename to LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/PacketLayerBase.cs.meta
index c181c7d..9455e2e 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/SimpleChannel.cs.meta
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/PacketLayerBase.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: cac7ecba35f9ec441897271b7f6db8e0
+guid: 0a34519fbc710e242bf64f27f1c7d6ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/XorEncryptLayer.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/XorEncryptLayer.cs
new file mode 100644
index 0000000..a258694
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/XorEncryptLayer.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Text;
+
+namespace LiteNetLib.Layers
+{
+ public class XorEncryptLayer : PacketLayerBase
+ {
+ private byte[] _byteKey;
+
+ public XorEncryptLayer() : base(0)
+ {
+
+ }
+
+ public XorEncryptLayer(byte[] key) : this()
+ {
+ SetKey(key);
+ }
+
+ public XorEncryptLayer(string key) : this()
+ {
+ SetKey(key);
+ }
+
+ public void SetKey(string key)
+ {
+ _byteKey = Encoding.UTF8.GetBytes(key);
+ }
+
+ public void SetKey(byte[] key)
+ {
+ if(_byteKey.Length != key.Length)
+ _byteKey = new byte[key.Length];
+ Buffer.BlockCopy(key, 0, _byteKey, 0, key.Length);
+ }
+
+ public override void ProcessInboundPacket(ref byte[] data, ref int length)
+ {
+ if (_byteKey == null)
+ return;
+ for (var i = 0; i < length; i++)
+ {
+ var offset = i % _byteKey.Length;
+ data[i] = (byte)(data[i] ^ _byteKey[offset]);
+ }
+ }
+
+ public override void ProcessOutBoundPacket(ref byte[] data, ref int offset, ref int length)
+ {
+ if (_byteKey == null)
+ return;
+ var cur = offset;
+ for (var i = 0; i < length; i++, cur++)
+ {
+ data[cur] = (byte)(data[cur] ^ _byteKey[i % _byteKey.Length]);
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListInitializer.cs.meta b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/XorEncryptLayer.cs.meta
similarity index 83%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListInitializer.cs.meta
rename to LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/XorEncryptLayer.cs.meta
index d3f5278..d3f19e9 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListInitializer.cs.meta
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Layers/XorEncryptLayer.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 97068e5d8cc14490b85933feb119d827
+guid: 041fb6002d777ee409062bf5035189e8
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetConstants.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetConstants.cs
index 81a4db4..c888934 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetConstants.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetConstants.cs
@@ -44,7 +44,7 @@ public static class NetConstants
public const int HeaderSize = 1;
public const int ChanneledHeaderSize = 4;
public const int FragmentHeaderSize = 6;
- public const int FragmentTotalSize = ChanneledHeaderSize + FragmentHeaderSize;
+ public const int FragmentedHeaderTotalSize = ChanneledHeaderSize + FragmentHeaderSize;
public const ushort MaxSequence = 32768;
public const ushort HalfMaxSequence = MaxSequence / 2;
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetManager.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetManager.cs
index b2049b9..9ec2409 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetManager.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetManager.cs
@@ -1,7 +1,3 @@
-#if DEBUG
-#define STATS_ENABLED
-#endif
-
using System;
using System.Collections;
using System.Collections.Generic;
@@ -9,11 +5,12 @@
using System.Net;
using System.Net.Sockets;
using System.Threading;
+using LiteNetLib.Layers;
using LiteNetLib.Utils;
namespace LiteNetLib
{
- public class NetPacketReader : NetDataReader
+ public sealed class NetPacketReader : NetDataReader
{
private NetPacket _packet;
private readonly NetManager _manager;
@@ -33,7 +30,7 @@ internal void SetSource(NetPacket packet)
SetSource(packet.RawData, packet.GetHeaderSize(), packet.Size);
}
- public void Recycle()
+ internal void RecycleInternal()
{
Clear();
if (_packet != null)
@@ -41,6 +38,13 @@ public void Recycle()
_packet = null;
_manager.RecycleEvent(_evt);
}
+
+ public void Recycle()
+ {
+ if(_manager.AutoRecycle)
+ throw new Exception("Recycle called with AutoRecycle enabled");
+ RecycleInternal();
+ }
}
internal sealed class NetEvent
@@ -78,13 +82,13 @@ public NetEvent(NetManager manager)
///
/// Main class for all network operations. Can be used as client and/or server.
///
- public class NetManager : INetSocketListener, IConnectionRequestListener, IEnumerable
+ public class NetManager : INetSocketListener, IEnumerable
{
private class IPEndPointComparer : IEqualityComparer
{
public bool Equals(IPEndPoint x, IPEndPoint y)
{
- return x.Equals(y);
+ return x.Address.Equals(y.Address) && x.Port == y.Port;
}
public int GetHashCode(IPEndPoint obj)
@@ -152,10 +156,13 @@ private struct IncomingData
private readonly IDeliveryEventListener _deliveryEventListener;
private readonly Dictionary _peersDict;
+ private readonly Dictionary _requestsDict;
private readonly ReaderWriterLockSlim _peersLock;
private volatile NetPeer _headPeer;
private volatile int _connectedPeersCount;
private readonly List _connectedPeerListCache;
+ private NetPeer[] _peersArray;
+ internal readonly PacketLayerBase _extraPacketLayer;
private int _lastPeerId;
private readonly Queue _peerIds;
private byte _channelsCount = 1;
@@ -249,6 +256,11 @@ private struct IncomingData
///
public readonly NetStatistics Statistics;
+ ///
+ /// Toggles the collection of network statistics for the instance and all known peers
+ ///
+ public bool EnableStatistics = false;
+
//modules
///
/// NatPunchModule for NAT hole punching operations
@@ -258,7 +270,7 @@ private struct IncomingData
///
/// Returns true if socket listening and update thread is running
///
- public bool IsRunning { get; private set; }
+ public bool IsRunning { get { return _socket.IsRunning; } }
///
/// Local EndPoint (host and port)
@@ -291,7 +303,7 @@ public byte ChannelsCount
get { return _channelsCount; }
set
{
- if(value < 1 || value > 64)
+ if (value < 1 || value > 64)
throw new ArgumentException("Channels count must be between 1 and 64");
_channelsCount = value;
}
@@ -304,20 +316,25 @@ public List ConnectedPeerList
{
get
{
- _connectedPeerListCache.Clear();
- for(var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
- {
- if ((netPeer.ConnectionState & ConnectionState.Connected) != 0)
- _connectedPeerListCache.Add(netPeer);
- }
+ GetPeersNonAlloc(_connectedPeerListCache, ConnectionState.Connected);
return _connectedPeerListCache;
}
}
+ ///
+ /// Gets peer by peer id
+ ///
+ /// id of peer
+ /// Peer if peer with id exist, otherwise null
+ public NetPeer GetPeerById(int id)
+ {
+ return _peersArray[id];
+ }
+
///
/// Returns connected peers count
///
- public int PeersCount { get { return _connectedPeersCount; } }
+ public int ConnectedPeersCount { get { return _connectedPeersCount; } }
private bool TryGetPeer(IPEndPoint endPoint, out NetPeer peer)
{
@@ -327,19 +344,8 @@ private bool TryGetPeer(IPEndPoint endPoint, out NetPeer peer)
return result;
}
- private NetPeer TryAddPeer(NetPeer peer)
+ private void AddPeer(NetPeer peer)
{
- _peersLock.EnterUpgradeableReadLock();
- NetPeer existingPeer;
- if (_peersDict.TryGetValue(peer.EndPoint, out existingPeer))
- {
- //return back unused peerId
- lock (_peerIds)
- _peerIds.Enqueue(peer.Id);
-
- _peersLock.ExitUpgradeableReadLock();
- return existingPeer;
- }
_peersLock.EnterWriteLock();
if (_headPeer != null)
{
@@ -348,9 +354,15 @@ private NetPeer TryAddPeer(NetPeer peer)
}
_headPeer = peer;
_peersDict.Add(peer.EndPoint, peer);
+ if (peer.Id >= _peersArray.Length)
+ {
+ int newSize = _peersArray.Length * 2;
+ while (peer.Id >= newSize)
+ newSize *= 2;
+ Array.Resize(ref _peersArray, newSize);
+ }
+ _peersArray[peer.Id] = peer;
_peersLock.ExitWriteLock();
- _peersLock.ExitUpgradeableReadLock();
- return peer;
}
private void RemovePeer(NetPeer peer)
@@ -373,6 +385,7 @@ private void RemovePeerInternal(NetPeer peer)
peer.NextPeer.PrevPeer = peer.PrevPeer;
peer.PrevPeer = null;
+ _peersArray[peer.Id] = null;
lock (_peerIds)
_peerIds.Enqueue(peer.Id);
}
@@ -381,7 +394,8 @@ private void RemovePeerInternal(NetPeer peer)
/// NetManager constructor
///
/// Network events listener (also can implement IDeliveryEventListener)
- public NetManager(INetEventListener listener)
+ /// Extra processing of packages, like CRC checksum or encryption. All connected NetManagers must have same layer.
+ public NetManager(INetEventListener listener, PacketLayerBase extraPacketLayer = null)
{
_socket = new NetSocket(this);
_netEventListener = listener;
@@ -393,8 +407,11 @@ public NetManager(INetEventListener listener)
Statistics = new NetStatistics();
_connectedPeerListCache = new List();
_peersDict = new Dictionary(new IPEndPointComparer());
+ _requestsDict = new Dictionary(new IPEndPointComparer());
_peersLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
_peerIds = new Queue();
+ _peersArray = new NetPeer[32];
+ _extraPacketLayer = extraPacketLayer;
}
internal void ConnectionLatencyUpdated(NetPeer fromPeer, int latency)
@@ -422,11 +439,25 @@ internal int SendRaw(NetPacket packet, IPEndPoint remoteEndPoint)
internal int SendRaw(byte[] message, int start, int length, IPEndPoint remoteEndPoint)
{
- if (!IsRunning)
+ if (!_socket.IsRunning)
return 0;
SocketError errorCode = 0;
- int result = _socket.SendTo(message, start, length, remoteEndPoint, ref errorCode);
+ int result;
+ if (_extraPacketLayer != null)
+ {
+ var expandedPacket = NetPacketPool.GetPacket(length + _extraPacketLayer.ExtraPacketSizeForLayer);
+ Buffer.BlockCopy(message, start, expandedPacket.RawData, 0, length);
+ int newStart = 0;
+ _extraPacketLayer.ProcessOutBoundPacket(ref expandedPacket.RawData, ref newStart, ref length);
+ result = _socket.SendTo(expandedPacket.RawData, newStart, length, remoteEndPoint, ref errorCode);
+ NetPacketPool.Recycle(expandedPacket);
+ }
+ else
+ {
+ result = _socket.SendTo(message, start, length, remoteEndPoint, ref errorCode);
+ }
+
NetPeer fromPeer;
switch (errorCode)
{
@@ -443,17 +474,16 @@ internal int SendRaw(byte[] message, int start, int length, IPEndPoint remoteEnd
DisconnectPeerForce(fromPeer, DisconnectReason.NetworkUnreachable, errorCode, null);
CreateEvent(NetEvent.EType.Error, remoteEndPoint: remoteEndPoint, errorCode: errorCode);
return -1;
- case SocketError.ConnectionReset: //connection reset (connection closed)
- if (TryGetPeer(remoteEndPoint, out fromPeer))
- DisconnectPeerForce(fromPeer, DisconnectReason.RemoteConnectionClose, errorCode, null);
- return -1;
}
if (result <= 0)
return 0;
-#if STATS_ENABLED
- Statistics.PacketsSent++;
- Statistics.BytesSent += (uint)length;
-#endif
+
+ if (EnableStatistics)
+ {
+ Statistics.PacketsSent++;
+ Statistics.BytesSent += (uint)length;
+ }
+
return result;
}
@@ -475,10 +505,10 @@ private void DisconnectPeer(
int count,
NetPacket eventData)
{
- bool wasConnected = peer.ConnectionState == ConnectionState.Connected;
- if (!peer.Shutdown(data, start, count, force))
+ var shutdownResult = peer.Shutdown(data, start, count, force);
+ if (shutdownResult == ShutdownResult.None)
return;
- if(wasConnected)
+ if(shutdownResult == ShutdownResult.WasConnected)
_connectedPeersCount--;
CreateEvent(
NetEvent.EType.Disconnect,
@@ -500,7 +530,7 @@ private void CreateEvent(
NetPacket readerSource = null,
object userData = null)
{
- NetEvent evt = null;
+ NetEvent evt;
bool unsyncEvent = UnsyncedEvents;
if (type == NetEvent.EType.Connect)
@@ -510,11 +540,8 @@ private void CreateEvent(
lock (_netEventsPool)
{
- if (_netEventsPool.Count > 0)
- evt = _netEventsPool.Pop();
+ evt = _netEventsPool.Count > 0 ? _netEventsPool.Pop() : new NetEvent(this);
}
- if(evt == null)
- evt = new NetEvent(this);
evt.Type = type;
evt.DataReader.SetSource(readerSource);
evt.Peer = peer;
@@ -581,7 +608,7 @@ private void ProcessEvent(NetEvent evt)
if (emptyData)
RecycleEvent(evt);
else if (AutoRecycle)
- evt.DataReader.Recycle();
+ evt.DataReader.RecycleInternal();
}
internal void RecycleEvent(NetEvent evt)
@@ -601,7 +628,7 @@ private void UpdateLogic()
var stopwatch = new Stopwatch();
stopwatch.Start();
- while (IsRunning)
+ while (_socket.IsRunning)
{
#if DEBUG
if (SimulateLatency)
@@ -623,13 +650,14 @@ private void UpdateLogic()
}
#endif
-#if STATS_ENABLED
ulong totalPacketLoss = 0;
-#endif
+
int elapsed = (int)stopwatch.ElapsedMilliseconds;
- if (elapsed <= 0)
- elapsed = 1;
- for(var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
+ elapsed = elapsed <= 0 ? 1 : elapsed;
+ stopwatch.Reset();
+ stopwatch.Start();
+
+ for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
{
if (netPeer.ConnectionState == ConnectionState.Disconnected && netPeer.TimeSinceLastPacket > DisconnectTimeout)
{
@@ -638,9 +666,11 @@ private void UpdateLogic()
else
{
netPeer.Update(elapsed);
-#if STATS_ENABLED
- totalPacketLoss += netPeer.Statistics.PacketLoss;
-#endif
+
+ if (EnableStatistics)
+ {
+ totalPacketLoss += netPeer.Statistics.PacketLoss;
+ }
}
}
if (peersToRemove.Count > 0)
@@ -650,13 +680,14 @@ private void UpdateLogic()
RemovePeerInternal(peersToRemove[i]);
_peersLock.ExitWriteLock();
peersToRemove.Clear();
- }
-#if STATS_ENABLED
- Statistics.PacketLoss = totalPacketLoss;
-#endif
- int sleepTime = UpdateTime - (int)(stopwatch.ElapsedMilliseconds - elapsed);
- stopwatch.Reset();
- stopwatch.Start();
+ }
+
+ if (EnableStatistics)
+ {
+ Statistics.PacketLoss = totalPacketLoss;
+ }
+
+ int sleepTime = UpdateTime - (int)stopwatch.ElapsedMilliseconds;
if (sleepTime > 0)
Thread.Sleep(sleepTime);
}
@@ -711,34 +742,62 @@ void INetSocketListener.OnMessageReceived(byte[] data, int length, SocketError e
}
}
- void IConnectionRequestListener.OnConnectionSolved(ConnectionRequest request, byte[] rejectData, int start, int length)
+ internal NetPeer OnConnectionSolved(ConnectionRequest request, byte[] rejectData, int start, int length)
{
- if (request.Result == ConnectionRequestResult.Reject)
+ NetPeer netPeer = null;
+
+ if (request.Result == ConnectionRequestResult.RejectForce)
{
- NetDebug.Write(NetLogLevel.Trace, "[NM] Peer connect reject.");
- request.Peer.Reject(request.ConnectionId, request.ConnectionNumber, rejectData, start, length);
+ NetDebug.Write(NetLogLevel.Trace, "[NM] Peer connect reject force.");
+ if (rejectData != null && length > 0)
+ {
+ var shutdownPacket = NetPacketPool.GetWithProperty(PacketProperty.Disconnect, length);
+ shutdownPacket.ConnectionNumber = request.ConnectionNumber;
+ FastBitConverter.GetBytes(shutdownPacket.RawData, 1, request.ConnectionTime);
+ if (shutdownPacket.Size >= NetConstants.PossibleMtu[0])
+ NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU!");
+ else
+ Buffer.BlockCopy(rejectData, start, shutdownPacket.RawData, 9, length);
+ SendRawAndRecycle(shutdownPacket, request.RemoteEndPoint);
+ }
}
else
{
- //Accept
- request.Peer.Accept(request.ConnectionId, request.ConnectionNumber);
- //TODO: sync
- //Add event
- CreateEvent(NetEvent.EType.Connect, request.Peer);
-
- NetDebug.Write(NetLogLevel.Trace, "[NM] Received peer connection Id: {0}, EP: {1}",
- request.Peer.ConnectTime, request.Peer.EndPoint);
+ _peersLock.EnterUpgradeableReadLock();
+ if (_peersDict.TryGetValue(request.RemoteEndPoint, out netPeer))
+ {
+ //already have peer
+ _peersLock.ExitUpgradeableReadLock();
+ }
+ else if (request.Result == ConnectionRequestResult.Reject)
+ {
+ netPeer = new NetPeer(this, request.RemoteEndPoint, GetNextPeerId());
+ netPeer.Reject(request.ConnectionTime, request.ConnectionNumber, rejectData, start, length);
+ AddPeer(netPeer);
+ _peersLock.ExitUpgradeableReadLock();
+ NetDebug.Write(NetLogLevel.Trace, "[NM] Peer connect reject.");
+ }
+ else //Accept
+ {
+ netPeer = new NetPeer(this, request.RemoteEndPoint, GetNextPeerId(), request.ConnectionTime, request.ConnectionNumber);
+ AddPeer(netPeer);
+ _peersLock.ExitUpgradeableReadLock();
+ CreateEvent(NetEvent.EType.Connect, netPeer);
+ NetDebug.Write(NetLogLevel.Trace, "[NM] Received peer connection Id: {0}, EP: {1}",
+ netPeer.ConnectTime, netPeer.EndPoint);
+ }
}
+
+ lock(_requestsDict)
+ _requestsDict.Remove(request.RemoteEndPoint);
+
+ return netPeer;
}
private int GetNextPeerId()
{
lock (_peerIds)
- {
- if (_peerIds.Count == 0)
- return _lastPeerId++;
- return _peerIds.Dequeue();
- }
+ return _peerIds.Count == 0 ? _lastPeerId++ : _peerIds.Dequeue();
}
private void ProcessConnectRequest(
@@ -747,16 +806,22 @@ private void ProcessConnectRequest(
NetConnectRequestPacket connRequest)
{
byte connectionNumber = connRequest.ConnectionNumber;
+ ConnectionRequest req;
//if we have peer
if (netPeer != null)
{
- NetDebug.Write("ConnectRequest LastId: {0}, NewId: {1}, EP: {2}", netPeer.ConnectTime, connRequest.ConnectionTime, remoteEndPoint);
var processResult = netPeer.ProcessConnectRequest(connRequest);
+ NetDebug.Write("ConnectRequest LastId: {0}, NewId: {1}, EP: {2}, Result: {3}",
+ netPeer.ConnectTime,
+ connRequest.ConnectionTime,
+ remoteEndPoint,
+ processResult);
+
switch (processResult)
{
case ConnectRequestResult.Reconnection:
- DisconnectPeerForce(netPeer, DisconnectReason.RemoteConnectionClose, 0, null);
+ DisconnectPeerForce(netPeer, DisconnectReason.Reconnect, 0, null);
RemovePeer(netPeer);
//go to new connection
break;
@@ -765,16 +830,18 @@ private void ProcessConnectRequest(
//go to new connection
break;
case ConnectRequestResult.P2PConnection:
- CreateEvent(
- NetEvent.EType.ConnectionRequest,
- connectionRequest: new ConnectionRequest(
+ lock (_requestsDict)
+ {
+ req = new ConnectionRequest(
netPeer.ConnectTime,
connectionNumber,
ConnectionRequestType.PeerToPeer,
connRequest.Data,
- netPeer,
- this)
- );
+ remoteEndPoint,
+ this);
+ _requestsDict.Add(remoteEndPoint, req);
+ }
+ CreateEvent(NetEvent.EType.ConnectionRequest, connectionRequest: req);
return;
default:
//no operations needed
@@ -789,29 +856,44 @@ private void ProcessConnectRequest(
{
NetDebug.Write("ConnectRequest Id: {0}, EP: {1}", connRequest.ConnectionTime, remoteEndPoint);
}
- //Add new peer and craete ConnectRequest event
- NetDebug.Write("[NM] Creating request event: " + connRequest.ConnectionTime);
- netPeer = new NetPeer(this, remoteEndPoint, GetNextPeerId());
- if (TryAddPeer(netPeer) == netPeer)
+
+ lock (_requestsDict)
{
- CreateEvent(NetEvent.EType.ConnectionRequest, connectionRequest: new ConnectionRequest(
+ if (_requestsDict.TryGetValue(remoteEndPoint, out req))
+ {
+ req.UpdateRequest(connRequest);
+ return;
+ }
+ req = new ConnectionRequest(
connRequest.ConnectionTime,
connectionNumber,
ConnectionRequestType.Incoming,
connRequest.Data,
- netPeer,
- this));
+ remoteEndPoint,
+ this);
+ _requestsDict.Add(remoteEndPoint, req);
}
+ NetDebug.Write("[NM] Creating request event: " + connRequest.ConnectionTime);
+ CreateEvent(NetEvent.EType.ConnectionRequest, connectionRequest: req);
}
private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEndPoint)
{
-#if STATS_ENABLED
- Statistics.PacketsReceived++;
- Statistics.BytesReceived += (uint) count;
-#endif
+ if (EnableStatistics)
+ {
+ Statistics.PacketsReceived++;
+ Statistics.BytesReceived += (uint)count;
+ }
+
+ if (_extraPacketLayer != null)
+ {
+ _extraPacketLayer.ProcessInboundPacket(ref reusableBuffer, ref count);
+ if (count == 0)
+ return;
+ }
+
//Try read packet
- NetPacket packet = NetPacketPool.GetPacket(count, false);
+ NetPacket packet = NetPacketPool.GetPacket(count);
if (!packet.FromBytes(reusableBuffer, 0, count))
{
NetPacketPool.Recycle(packet);
@@ -819,13 +901,33 @@ private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEnd
return;
}
- //get peer
- //Check normal packets
NetPeer netPeer;
- //old packets protection
- bool peerFound = TryGetPeer(remoteEndPoint, out netPeer);
- //Check unconnected
+ //special case connect request
+ if (packet.Property == PacketProperty.ConnectRequest)
+ {
+ if (NetConnectRequestPacket.GetProtocolId(packet) != NetConstants.ProtocolId)
+ {
+ SendRawAndRecycle(NetPacketPool.GetWithProperty(PacketProperty.InvalidProtocol), remoteEndPoint);
+ return;
+ }
+ var connRequest = NetConnectRequestPacket.FromData(packet);
+ if (connRequest != null)
+ {
+ _peersLock.EnterUpgradeableReadLock();
+ _peersDict.TryGetValue(remoteEndPoint, out netPeer);
+ //here new peer can be created
+ ProcessConnectRequest(remoteEndPoint, netPeer, connRequest);
+ _peersLock.ExitUpgradeableReadLock();
+ }
+ return;
+ }
+
+ _peersLock.EnterReadLock();
+ bool peerFound = _peersDict.TryGetValue(remoteEndPoint, out netPeer);
+ _peersLock.ExitReadLock();
+
+ //Check normal packets
switch (packet.Property)
{
case PacketProperty.PeerNotFound:
@@ -840,12 +942,12 @@ private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEnd
p.RawData[1] = 0;
FastBitConverter.GetBytes(p.RawData, 2, netPeer.ConnectTime);
SendRawAndRecycle(p, remoteEndPoint);
- NetDebug.Write("PeerNotFound sending connectId: {0}", netPeer.ConnectTime);
+ NetDebug.Write("PeerNotFound sending connectTime: {0}", netPeer.ConnectTime);
}
else if (packet.Size == 10 && packet.RawData[1] == 1 && BitConverter.ToInt64(packet.RawData, 2) == netPeer.ConnectTime)
{
//second reply
- NetDebug.Write("PeerNotFound received our connectId: {0}", netPeer.ConnectTime);
+ NetDebug.Write("PeerNotFound received our connectTime: {0}", netPeer.ConnectTime);
DisconnectPeerForce(netPeer, DisconnectReason.RemoteConnectionClose, 0, null);
}
}
@@ -875,7 +977,7 @@ private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEnd
NatPunchModule.ProcessMessage(remoteEndPoint, packet);
break;
case PacketProperty.InvalidProtocol:
- if (peerFound && netPeer.ConnectionState == ConnectionState.Outcoming)
+ if (peerFound && netPeer.ConnectionState == ConnectionState.Outgoing)
DisconnectPeerForce(netPeer, DisconnectReason.InvalidProtocol, 0, null);
break;
case PacketProperty.Disconnect:
@@ -899,7 +1001,7 @@ private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEnd
NetPacketPool.Recycle(packet);
}
//Send shutdown
- SendRawAndRecycle(NetPacketPool.GetWithProperty(PacketProperty.ShutdownOk, 0), remoteEndPoint);
+ SendRawAndRecycle(NetPacketPool.GetWithProperty(PacketProperty.ShutdownOk), remoteEndPoint);
break;
case PacketProperty.ConnectAccept:
@@ -907,31 +1009,35 @@ private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEnd
if (connAccept != null && peerFound && netPeer.ProcessConnectAccept(connAccept))
CreateEvent(NetEvent.EType.Connect, netPeer);
break;
- case PacketProperty.ConnectRequest:
- if (NetConnectRequestPacket.GetProtocolId(packet) != NetConstants.ProtocolId)
- {
- SendRawAndRecycle(NetPacketPool.GetWithProperty(PacketProperty.InvalidProtocol, 0), remoteEndPoint);
- break;
- }
- var connRequest = NetConnectRequestPacket.FromData(packet);
- if (connRequest != null)
- ProcessConnectRequest(remoteEndPoint, netPeer, connRequest);
- break;
default:
if(peerFound)
netPeer.ProcessPacket(packet);
else
- SendRawAndRecycle(NetPacketPool.GetWithProperty(PacketProperty.PeerNotFound, 0), remoteEndPoint);
+ SendRawAndRecycle(NetPacketPool.GetWithProperty(PacketProperty.PeerNotFound), remoteEndPoint);
break;
}
}
- internal void ReceiveFromPeer(NetPacket packet, NetPeer fromPeer)
+ internal void CreateReceiveEvent(NetPacket packet, DeliveryMethod method, NetPeer fromPeer)
{
- var deliveryMethod = packet.Property == PacketProperty.Channeled
- ? (DeliveryMethod) (packet.ChannelId % 4)
- : DeliveryMethod.Unreliable;
- CreateEvent(NetEvent.EType.Receive, fromPeer, deliveryMethod: deliveryMethod, readerSource: packet);
+ NetEvent evt;
+ lock (_netEventsPool)
+ {
+ evt = _netEventsPool.Count > 0 ? _netEventsPool.Pop() : new NetEvent(this);
+ }
+ evt.Type = NetEvent.EType.Receive;
+ evt.DataReader.SetSource(packet);
+ evt.Peer = fromPeer;
+ evt.DeliveryMethod = method;
+ if (UnsyncedEvents)
+ {
+ ProcessEvent(evt);
+ }
+ else
+ {
+ lock (_netEventsQueue)
+ _netEventsQueue.Enqueue(evt);
+ }
}
///
@@ -998,8 +1104,16 @@ public void SendToAll(byte[] data, byte channelNumber, DeliveryMethod options)
/// Send options (reliable, unreliable, etc.)
public void SendToAll(byte[] data, int start, int length, byte channelNumber, DeliveryMethod options)
{
- for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
- netPeer.Send(data, start, length, channelNumber, options);
+ try
+ {
+ _peersLock.EnterReadLock();
+ for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
+ netPeer.Send(data, start, length, channelNumber, options);
+ }
+ finally
+ {
+ _peersLock.ExitReadLock();
+ }
}
///
@@ -1073,10 +1187,18 @@ public void SendToAll(byte[] data, byte channelNumber, DeliveryMethod options, N
/// Excluded peer
public void SendToAll(byte[] data, int start, int length, byte channelNumber, DeliveryMethod options, NetPeer excludePeer)
{
- for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
+ try
{
- if (netPeer != excludePeer)
- netPeer.Send(data, start, length, channelNumber, options);
+ _peersLock.EnterReadLock();
+ for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
+ {
+ if (netPeer != excludePeer)
+ netPeer.Send(data, start, length, channelNumber, options);
+ }
+ }
+ finally
+ {
+ _peersLock.ExitReadLock();
}
}
@@ -1096,11 +1218,8 @@ public bool Start()
/// port to listen
public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port)
{
- if (IsRunning)
- return false;
if (!_socket.Bind(addressIPv4, addressIPv6, port, ReuseAddress, IPv6Enabled))
return false;
- IsRunning = true;
_logicThread = new Thread(UpdateLogic) { Name = "LogicThread", IsBackground = true };
_logicThread.Start();
return true;
@@ -1160,11 +1279,9 @@ public bool SendUnconnectedMessage(NetDataWriter writer, IPEndPoint remoteEndPoi
/// Operation result
public bool SendUnconnectedMessage(byte[] message, int start, int length, IPEndPoint remoteEndPoint)
{
- if (!IsRunning)
- return false;
- var packet = NetPacketPool.GetWithData(PacketProperty.UnconnectedMessage, message, start, length);
- bool result = SendRawAndRecycle(packet, remoteEndPoint) > 0;
- return result;
+ //No need for CRC here, SendRaw does that
+ NetPacket packet = NetPacketPool.GetWithData(PacketProperty.UnconnectedMessage, message, start, length);
+ return SendRawAndRecycle(packet, remoteEndPoint) > 0;
}
public bool SendBroadcast(NetDataWriter writer, int port)
@@ -1179,9 +1296,22 @@ public bool SendBroadcast(byte[] data, int port)
public bool SendBroadcast(byte[] data, int start, int length, int port)
{
- if (!IsRunning)
- return false;
- var packet = NetPacketPool.GetWithData(PacketProperty.Broadcast, data, start, length);
+ NetPacket packet;
+ if (_extraPacketLayer != null)
+ {
+ var headerSize = NetPacket.GetHeaderSize(PacketProperty.Broadcast);
+ packet = NetPacketPool.GetPacket(headerSize + length + _extraPacketLayer.ExtraPacketSizeForLayer);
+ packet.Property = PacketProperty.Broadcast;
+ Buffer.BlockCopy(data, start, packet.RawData, headerSize, length);
+ var checksumComputeStart = 0;
+ int preCrcLength = length + headerSize;
+ _extraPacketLayer.ProcessOutBoundPacket(ref packet.RawData, ref checksumComputeStart, ref preCrcLength);
+ }
+ else
+ {
+ packet = NetPacketPool.GetWithData(PacketProperty.Broadcast, data, start, length);
+ }
+
bool result = _socket.SendBroadcast(packet.RawData, 0, packet.Size, port);
NetPacketPool.Recycle(packet);
return result;
@@ -1270,32 +1400,42 @@ public NetPeer Connect(IPEndPoint target, string key)
///
/// Server end point (ip and port)
/// Additional data for remote peer
- /// New NetPeer if new connection, Old NetPeer if already connected
+ /// New NetPeer if new connection, Old NetPeer if already connected, null peer if there is ConnectionRequest awaiting
/// Manager is not running. Call
public NetPeer Connect(IPEndPoint target, NetDataWriter connectionData)
{
- if (!IsRunning)
+ if (!_socket.IsRunning)
throw new InvalidOperationException("Client is not running");
NetPeer peer;
byte connectionNumber = 0;
- if (TryGetPeer(target, out peer))
+
+ if (_requestsDict.ContainsKey(target))
+ return null;
+
+ _peersLock.EnterUpgradeableReadLock();
+ if (_peersDict.TryGetValue(target, out peer))
{
switch (peer.ConnectionState)
{
//just return already connected peer
case ConnectionState.Connected:
- case ConnectionState.Outcoming:
- case ConnectionState.Incoming:
+ case ConnectionState.Outgoing:
+ _peersLock.ExitUpgradeableReadLock();
return peer;
}
//else reconnect
connectionNumber = (byte)((peer.ConnectionNum + 1) % NetConstants.MaxConnectionNumber);
RemovePeer(peer);
}
+
//Create reliable connection
//And send connection request
- return TryAddPeer(new NetPeer(this, target, GetNextPeerId(), connectionNumber, connectionData));
+ peer = new NetPeer(this, target, GetNextPeerId(), connectionNumber, connectionData);
+ AddPeer(peer);
+ _peersLock.ExitUpgradeableReadLock();
+
+ return peer;
}
///
@@ -1312,7 +1452,7 @@ public void Stop()
/// Send disconnect messages
public void Stop(bool sendDisconnectMessages)
{
- if (!IsRunning)
+ if (!_socket.IsRunning)
return;
NetDebug.Write("[NM] Stop");
@@ -1320,19 +1460,19 @@ public void Stop(bool sendDisconnectMessages)
for(var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
netPeer.Shutdown(null, 0, 0, !sendDisconnectMessages);
- //For working send
- IsRunning = false;
-
//Stop
+ _socket.Close(false);
_logicThread.Join();
_logicThread = null;
- _socket.Close();
//clear peers
_peersLock.EnterWriteLock();
_headPeer = null;
_peersDict.Clear();
+ _peersArray = new NetPeer[32];
_peersLock.ExitWriteLock();
+ lock(_peerIds)
+ _peerIds.Clear();
#if DEBUG
lock (_pingSimulationList)
_pingSimulationList.Clear();
@@ -1350,35 +1490,16 @@ public void Stop(bool sendDisconnectMessages)
public int GetPeersCount(ConnectionState peerState)
{
int count = 0;
+ _peersLock.EnterReadLock();
for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
{
if ((netPeer.ConnectionState & peerState) != 0)
count++;
}
+ _peersLock.ExitReadLock();
return count;
}
- ///
- /// Get copy of current connected peers (slow! use GetPeersNonAlloc for best performance)
- ///
- /// Array with connected peers
- [Obsolete("Use GetPeers(ConnectionState peerState)")]
- public NetPeer[] GetPeers()
- {
- return GetPeers(ConnectionState.Connected | ConnectionState.Outcoming);
- }
-
- ///
- /// Get copy of current connected peers (slow! use GetPeersNonAlloc for best performance)
- ///
- /// Array with connected peers
- public NetPeer[] GetPeers(ConnectionState peerState)
- {
- List peersList = new List();
- GetPeersNonAlloc(peersList, peerState);
- return peersList.ToArray();
- }
-
///
/// Get copy of peers (without allocations)
///
@@ -1387,11 +1508,13 @@ public NetPeer[] GetPeers(ConnectionState peerState)
public void GetPeersNonAlloc(List peers, ConnectionState peerState)
{
peers.Clear();
+ _peersLock.EnterReadLock();
for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
{
if ((netPeer.ConnectionState & peerState) != 0)
peers.Add(netPeer);
}
+ _peersLock.ExitReadLock();
}
///
@@ -1411,6 +1534,7 @@ public void DisconnectAll()
public void DisconnectAll(byte[] data, int start, int count)
{
//Send disconnect packets
+ _peersLock.EnterReadLock();
for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer)
{
DisconnectPeer(
@@ -1423,6 +1547,7 @@ public void DisconnectAll(byte[] data, int start, int count)
count,
null);
}
+ _peersLock.ExitReadLock();
}
///
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPacket.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPacket.cs
index 9574f3e..190f4db 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPacket.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPacket.cs
@@ -84,7 +84,7 @@ public ushort FragmentsTotal
//Data
public byte[] RawData;
- public ushort Size;
+ public int Size;
//Delivery
public object UserData;
@@ -92,7 +92,7 @@ public ushort FragmentsTotal
public NetPacket(int size)
{
RawData = new byte[size];
- Size = (ushort)size;
+ Size = size;
}
public NetPacket(PacketProperty property, int size)
@@ -100,19 +100,7 @@ public NetPacket(PacketProperty property, int size)
size += GetHeaderSize(property);
RawData = new byte[size];
Property = property;
- Size = (ushort)size;
- }
-
- public void Realloc(int toSize, bool clear)
- {
- Size = (ushort)toSize;
- if (RawData.Length < toSize)
- {
- RawData = new byte[toSize];
- return;
- }
- if (clear) //clear not reallocated
- Array.Clear(RawData, 0, toSize);
+ Size = size;
}
public static int GetHeaderSize(PacketProperty property)
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPacketPool.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPacketPool.cs
index 57a3999..2f78845 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPacketPool.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPacketPool.cs
@@ -11,16 +11,33 @@ internal sealed class NetPacketPool
public NetPacket GetWithData(PacketProperty property, byte[] data, int start, int length)
{
- var packet = GetWithProperty(property, length);
- Buffer.BlockCopy(data, start, packet.RawData, NetPacket.GetHeaderSize(property), length);
+ int headerSize = NetPacket.GetHeaderSize(property);
+ NetPacket packet = GetPacket(length + headerSize);
+ packet.Property = property;
+ Buffer.BlockCopy(data, start, packet.RawData, headerSize, length);
+ return packet;
+ }
+
+ //Get packet with size
+ public NetPacket GetWithProperty(PacketProperty property, int size)
+ {
+ NetPacket packet = GetPacket(size + NetPacket.GetHeaderSize(property));
+ packet.Property = property;
return packet;
}
- public NetPacket GetPacket(int size, bool clear)
+ public NetPacket GetWithProperty(PacketProperty property)
+ {
+ NetPacket packet = GetPacket(NetPacket.GetHeaderSize(property));
+ packet.Property = property;
+ return packet;
+ }
+
+ public NetPacket GetPacket(int size)
{
- NetPacket packet = null;
if (size <= NetConstants.MaxPacketSize)
{
+ NetPacket packet = null;
_lock.EnterUpgradeableReadLock();
if (_count > 0)
{
@@ -31,27 +48,15 @@ public NetPacket GetPacket(int size, bool clear)
_lock.ExitWriteLock();
}
_lock.ExitUpgradeableReadLock();
+ if (packet != null)
+ {
+ packet.Size = size;
+ if (packet.RawData.Length < size)
+ packet.RawData = new byte[size];
+ return packet;
+ }
}
- if (packet == null)
- {
- //allocate new packet
- packet = new NetPacket(size);
- }
- else
- {
- //reallocate packet data if packet not fits
- packet.Realloc(size, clear);
- }
- return packet;
- }
-
- //Get packet with size
- public NetPacket GetWithProperty(PacketProperty property, int size)
- {
- size += NetPacket.GetHeaderSize(property);
- NetPacket packet = GetPacket(size, true);
- packet.Property = property;
- return packet;
+ return new NetPacket(size);
}
public void Recycle(NetPacket packet)
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPeer.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPeer.cs
index 2f13ac2..2218630 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPeer.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetPeer.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
+using System.Threading;
using LiteNetLib.Utils;
namespace LiteNetLib
@@ -15,12 +16,11 @@ namespace LiteNetLib
[Flags]
public enum ConnectionState : byte
{
- Incoming = 1 << 1,
- Outcoming = 1 << 2,
- Connected = 1 << 3,
- ShutdownRequested = 1 << 4,
- Disconnected = 1 << 5,
- Any = Incoming | Outcoming | Connected | ShutdownRequested
+ Outgoing = 1 << 1,
+ Connected = 1 << 2,
+ ShutdownRequested = 1 << 3,
+ Disconnected = 1 << 4,
+ Any = Outgoing | Connected | ShutdownRequested
}
internal enum ConnectRequestResult
@@ -38,6 +38,13 @@ internal enum DisconnectResult
Disconnect
}
+ internal enum ShutdownResult
+ {
+ None,
+ Success,
+ WasConnected
+ }
+
///
/// Network peer. Main purpose is sending messages to specific peer.
///
@@ -76,12 +83,12 @@ private set
}
//Channels
- private readonly SimpleChannel _unreliableChannel;
+ private readonly Queue _unreliableChannel;
private readonly BaseChannel[] _channels;
private BaseChannel _headChannel;
//MTU
- private int _mtu = NetConstants.PossibleMtu[0];
+ private int _mtu;
private int _mtuIdx;
private bool _finishMtu;
private int _mtuCheckTimer;
@@ -119,7 +126,7 @@ private class IncomingFragments
private readonly NetPacket _pingPacket;
private readonly NetPacket _pongPacket;
private readonly NetPacket _connectRequestPacket;
- private NetPacket _connectAcceptPacket;
+ private readonly NetPacket _connectAcceptPacket;
///
/// Peer ip address and port
@@ -197,20 +204,42 @@ internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id)
Statistics = new NetStatistics();
_packetPool = netManager.NetPacketPool;
NetManager = netManager;
+ SetMtu(0);
+
EndPoint = remoteEndPoint;
- _connectionState = ConnectionState.Incoming;
+ _connectionState = ConnectionState.Connected;
_mergeData = new NetPacket(PacketProperty.Merged, NetConstants.MaxPacketSize);
_pongPacket = new NetPacket(PacketProperty.Pong, 0);
_pingPacket = new NetPacket(PacketProperty.Ping, 0) {Sequence = 1};
- _unreliableChannel = new SimpleChannel(this);
- _headChannel = _unreliableChannel;
+ _unreliableChannel = new Queue(64);
+ _headChannel = null;
_holdedFragments = new Dictionary();
_deliveredFramgnets = new Dictionary();
_channels = new BaseChannel[netManager.ChannelsCount * 4];
}
+ private void SetMtu(int mtuIdx)
+ {
+ int extraLayerSpace = NetManager._extraPacketLayer != null ? NetManager._extraPacketLayer.ExtraPacketSizeForLayer : 0;
+ _mtu = NetConstants.PossibleMtu[mtuIdx] - extraLayerSpace;
+ }
+
+ ///
+ /// Returns packets count in queue for reliable channel
+ ///
+ /// number of channel 0-63
+ /// type of channel ReliableOrdered or ReliableUnordered
+ /// packets count in channel queue
+ public int GetPacketsCountInReliableQueue(byte channelNumber, bool ordered)
+ {
+ int idx = channelNumber * 4 +
+ (byte) (ordered ? DeliveryMethod.ReliableOrdered : DeliveryMethod.ReliableUnordered);
+ var channel = _channels[idx];
+ return channel != null ? ((ReliableChannel)channel).PacketsInQueue : 0;
+ }
+
private BaseChannel CreateChannel(byte idx)
{
BaseChannel newChannel = _channels[idx];
@@ -242,7 +271,7 @@ internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id, byte
: this(netManager, remoteEndPoint, id)
{
_connectTime = DateTime.UtcNow.Ticks;
- _connectionState = ConnectionState.Outcoming;
+ _connectionState = ConnectionState.Outgoing;
ConnectionNum = connectNum;
//Make initial packet
@@ -256,7 +285,8 @@ internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id, byte
}
//"Accept" incoming constructor
- internal void Accept(long connectId, byte connectNum)
+ internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id, long connectId, byte connectNum)
+ : this(netManager, remoteEndPoint, id)
{
_connectTime = connectId;
_connectionState = ConnectionState.Connected;
@@ -270,9 +300,17 @@ internal void Accept(long connectId, byte connectNum)
NetDebug.Write(NetLogLevel.Trace, "[CC] ConnectId: {0}", _connectTime);
}
+ //Reject
+ internal void Reject(long connectionId, byte connectionNumber, byte[] data, int start, int length)
+ {
+ _connectTime = connectionId;
+ _connectNum = connectionNumber;
+ Shutdown(data, start, length, false);
+ }
+
internal bool ProcessConnectAccept(NetConnectAcceptPacket packet)
{
- if (_connectionState != ConnectionState.Outcoming)
+ if (_connectionState != ConnectionState.Outgoing)
return false;
//check connection id
@@ -285,7 +323,7 @@ internal bool ProcessConnectAccept(NetConnectAcceptPacket packet)
ConnectionNum = packet.ConnectionNumber;
NetDebug.Write(NetLogLevel.Trace, "[NC] Received connection accept");
- _timeSinceLastPacket = 0;
+ Interlocked.Exchange(ref _timeSinceLastPacket, 0);
_connectionState = ConnectionState.Connected;
return true;
}
@@ -458,20 +496,16 @@ private void SendInternal(
DeliveryMethod deliveryMethod,
object userData)
{
- if (_connectionState == ConnectionState.ShutdownRequested ||
- _connectionState == ConnectionState.Disconnected)
- return;
- if (channelNumber >= _channels.Length)
+ if (_connectionState != ConnectionState.Connected || channelNumber >= _channels.Length)
return;
//Select channel
PacketProperty property;
- BaseChannel channel;
+ BaseChannel channel = null;
if (deliveryMethod == DeliveryMethod.Unreliable)
{
property = PacketProperty.Unreliable;
- channel = _unreliableChannel;
}
else
{
@@ -490,7 +524,7 @@ private void SendInternal(
{
//if cannot be fragmented
if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != DeliveryMethod.ReliableUnordered)
- throw new TooBigPacketException("Unreliable packet size exceeded maximum of " + (_mtu - headerSize) + " bytes");
+ throw new TooBigPacketException("Unreliable packet size exceeded maximum of " + (mtu - headerSize) + " bytes");
int packetFullSize = mtu - headerSize;
int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize;
@@ -507,34 +541,48 @@ private void SendInternal(
if (totalPackets > ushort.MaxValue)
throw new TooBigPacketException("Data was split in " + totalPackets + " fragments, which exceeds " + ushort.MaxValue);
+ ushort currentFramentId;
lock (_sendLock)
{
- for(ushort partIdx = 0; partIdx < totalPackets; partIdx++)
- {
- int sendLength = length > packetDataSize ? packetDataSize : length;
+ currentFramentId = _fragmentId;
+ _fragmentId++;
+ }
- NetPacket p = _packetPool.GetWithProperty(property, sendLength + NetConstants.FragmentHeaderSize);
- p.UserData = userData;
- p.FragmentId = _fragmentId;
- p.FragmentPart = partIdx;
- p.FragmentsTotal = (ushort)totalPackets;
- p.MarkFragmented();
+ for(ushort partIdx = 0; partIdx < totalPackets; partIdx++)
+ {
+ int sendLength = length > packetDataSize ? packetDataSize : length;
-
- Buffer.BlockCopy(data, partIdx * packetDataSize, p.RawData, NetConstants.FragmentTotalSize, sendLength);
- channel.AddToQueue(p);
+ NetPacket p = _packetPool.GetPacket(headerSize + sendLength + NetConstants.FragmentHeaderSize);
+ p.Property = property;
+ p.UserData = userData;
+ p.FragmentId = currentFramentId;
+ p.FragmentPart = partIdx;
+ p.FragmentsTotal = (ushort)totalPackets;
+ p.MarkFragmented();
- length -= sendLength;
- }
- _fragmentId++;
+ Buffer.BlockCopy(data, partIdx * packetDataSize, p.RawData, NetConstants.FragmentedHeaderTotalSize, sendLength);
+ channel.AddToQueue(p);
+
+ length -= sendLength;
}
return;
}
//Else just send
- NetPacket packet = _packetPool.GetWithData(property, data, start, length);
+ NetPacket packet = _packetPool.GetPacket(headerSize + length);
+ packet.Property = property;
+ Buffer.BlockCopy(data, start, packet.RawData, headerSize, length);
packet.UserData = userData;
- channel.AddToQueue(packet);
+
+ if (channel == null) //unreliable
+ {
+ lock(_unreliableChannel)
+ _unreliableChannel.Enqueue(packet);
+ }
+ else
+ {
+ channel.AddToQueue(packet);
+ }
}
public void Disconnect(byte[] data)
@@ -559,7 +607,7 @@ public void Disconnect()
internal DisconnectResult ProcessDisconnect(NetPacket packet)
{
- if ((_connectionState == ConnectionState.Connected || _connectionState == ConnectionState.Outcoming) &&
+ if ((_connectionState == ConnectionState.Connected || _connectionState == ConnectionState.Outgoing) &&
packet.Size >= 9 &&
BitConverter.ToInt64(packet.RawData, 1) == _connectTime &&
packet.ConnectionNumber == _connectNum)
@@ -571,14 +619,7 @@ internal DisconnectResult ProcessDisconnect(NetPacket packet)
return DisconnectResult.None;
}
- internal void Reject(long connectionId, byte connectionNumber, byte[] data, int start, int length)
- {
- _connectTime = connectionId;
- _connectNum = connectionNumber;
- Shutdown(data, start, length, false);
- }
-
- internal bool Shutdown(byte[] data, int start, int length, bool force)
+ internal ShutdownResult Shutdown(byte[] data, int start, int length, bool force)
{
lock (_shutdownLock)
{
@@ -586,22 +627,25 @@ internal bool Shutdown(byte[] data, int start, int length, bool force)
if (_connectionState == ConnectionState.Disconnected ||
_connectionState == ConnectionState.ShutdownRequested)
{
- return false;
+ return ShutdownResult.None;
}
+ var result = _connectionState == ConnectionState.Connected
+ ? ShutdownResult.WasConnected
+ : ShutdownResult.Success;
+
//don't send anything
if (force)
{
_connectionState = ConnectionState.Disconnected;
- return true;
+ return result;
}
//reset time for reconnect protection
- _timeSinceLastPacket = 0;
+ Interlocked.Exchange(ref _timeSinceLastPacket, 0);
//send shutdown packet
- _shutdownPacket = new NetPacket(PacketProperty.Disconnect, length);
- _shutdownPacket.ConnectionNumber = _connectNum;
+ _shutdownPacket = new NetPacket(PacketProperty.Disconnect, length) {ConnectionNumber = _connectNum};
FastBitConverter.GetBytes(_shutdownPacket.RawData, 1, _connectTime);
if (_shutdownPacket.Size >= _mtu)
{
@@ -615,7 +659,7 @@ internal bool Shutdown(byte[] data, int start, int length, bool force)
_connectionState = ConnectionState.ShutdownRequested;
NetDebug.Write("[Peer] Send disconnect");
NetManager.SendRaw(_shutdownPacket, EndPoint);
- return true;
+ return result;
}
}
@@ -627,7 +671,7 @@ private void UpdateRoundTripTime(int roundTripTime)
_resendDelay = 25.0 + _avgRtt * 2.1; // 25 ms + double rtt
}
- internal void AddIncomingPacket(NetPacket p)
+ internal void AddReliablePacket(DeliveryMethod method, NetPacket p)
{
if (p.IsFragmented)
{
@@ -664,42 +708,43 @@ internal void AddIncomingPacket(NetPacket p)
incomingFragments.ReceivedCount++;
//Increase total size
- incomingFragments.TotalSize += p.Size - NetConstants.FragmentTotalSize;
+ incomingFragments.TotalSize += p.Size - NetConstants.FragmentedHeaderTotalSize;
//Check for finish
if (incomingFragments.ReceivedCount != fragments.Length)
return;
- NetPacket resultingPacket = _packetPool.GetWithProperty( p.Property, incomingFragments.TotalSize );
- resultingPacket.ChannelId = incomingFragments.ChannelId;
+ //unreliable to save header space
+ NetPacket resultingPacket = _packetPool.GetWithProperty(
+ PacketProperty.Unreliable,
+ incomingFragments.TotalSize);
- int resultingPacketOffset = resultingPacket.GetHeaderSize();
- int firstFragmentSize = fragments[0].Size - NetConstants.FragmentTotalSize;
+ int firstFragmentSize = fragments[0].Size - NetConstants.FragmentedHeaderTotalSize;
for (int i = 0; i < incomingFragments.ReceivedCount; i++)
{
+ var fragment = fragments[i];
//Create resulting big packet
- int fragmentSize = fragments[i].Size - NetConstants.FragmentTotalSize;
Buffer.BlockCopy(
- fragments[i].RawData,
- NetConstants.FragmentTotalSize,
+ fragment.RawData,
+ NetConstants.FragmentedHeaderTotalSize,
resultingPacket.RawData,
- resultingPacketOffset + firstFragmentSize * i,
- fragmentSize);
+ NetConstants.HeaderSize + firstFragmentSize * i,
+ fragment.Size - NetConstants.FragmentedHeaderTotalSize);
//Free memory
- _packetPool.Recycle(fragments[i]);
- fragments[i] = null;
+ _packetPool.Recycle(fragment);
}
+ Array.Clear(fragments, 0, incomingFragments.ReceivedCount);
//Send to process
- NetManager.ReceiveFromPeer(resultingPacket, this);
+ NetManager.CreateReceiveEvent(resultingPacket, method, this);
//Clear memory
_holdedFragments.Remove(packetFragId);
}
else //Just simple packet
{
- NetManager.ReceiveFromPeer(p, this);
+ NetManager.CreateReceiveEvent(p, method, this);
}
}
@@ -734,7 +779,7 @@ private void ProcessMtuPacket(NetPacket packet)
lock (_mtuMutex)
{
_mtuIdx++;
- _mtu = receivedMtu;
+ SetMtu(_mtuIdx);
}
//if maxed - finish.
if (_mtuIdx == NetConstants.PossibleMtu.Length - 1)
@@ -768,7 +813,8 @@ private void UpdateMtuLogic(int deltaTime)
//Send increased packet
int newMtu = NetConstants.PossibleMtu[_mtuIdx + 1];
- var p = _packetPool.GetWithProperty(PacketProperty.MtuCheck, newMtu - NetConstants.HeaderSize);
+ var p = _packetPool.GetPacket(newMtu);
+ p.Property = PacketProperty.MtuCheck;
FastBitConverter.GetBytes(p.RawData, 1, newMtu); //place into start
FastBitConverter.GetBytes(p.RawData, p.Size - 4, newMtu);//and end of packet
@@ -784,8 +830,7 @@ internal ConnectRequestResult ProcessConnectRequest(NetConnectRequestPacket conn
switch (_connectionState)
{
//P2P case or just ID update
- case ConnectionState.Outcoming:
- case ConnectionState.Incoming:
+ case ConnectionState.Outgoing:
//change connect id if newer
if (connRequest.ConnectionTime >= _connectTime)
{
@@ -793,9 +838,7 @@ internal ConnectRequestResult ProcessConnectRequest(NetConnectRequestPacket conn
_connectTime = connRequest.ConnectionTime;
ConnectionNum = connRequest.ConnectionNumber;
}
- return _connectionState == ConnectionState.Outcoming
- ? ConnectRequestResult.P2PConnection
- : ConnectRequestResult.None;
+ return ConnectRequestResult.P2PConnection;
case ConnectionState.Connected:
//Old connect request
@@ -826,7 +869,7 @@ internal ConnectRequestResult ProcessConnectRequest(NetConnectRequestPacket conn
internal void ProcessPacket(NetPacket packet)
{
//not initialized
- if (_connectionState == ConnectionState.Incoming)
+ if (_connectionState == ConnectionState.Outgoing)
{
_packetPool.Recycle(packet);
return;
@@ -837,7 +880,7 @@ internal void ProcessPacket(NetPacket packet)
_packetPool.Recycle(packet);
return;
}
- _timeSinceLastPacket = 0;
+ Interlocked.Exchange(ref _timeSinceLastPacket, 0);
NetDebug.Write("[RR]PacketProperty: {0}", packet.Property);
switch (packet.Property)
@@ -848,7 +891,7 @@ internal void ProcessPacket(NetPacket packet)
{
ushort size = BitConverter.ToUInt16(packet.RawData, pos);
pos += 2;
- NetPacket mergedPacket = _packetPool.GetPacket(size, false);
+ NetPacket mergedPacket = _packetPool.GetPacket(size);
if (!mergedPacket.FromBytes(packet.RawData, pos, size))
{
_packetPool.Recycle(packet);
@@ -901,7 +944,7 @@ internal void ProcessPacket(NetPacket packet)
//Simple packet without acks
case PacketProperty.Unreliable:
- AddIncomingPacket(packet);
+ NetManager.CreateReceiveEvent(packet, DeliveryMethod.Unreliable, this);
return;
case PacketProperty.MtuCheck:
@@ -936,10 +979,13 @@ private void SendMerged()
//Send without length information and merging
bytesSent = NetManager.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, EndPoint);
}
-#if STATS_ENABLED
- Statistics.PacketsSent++;
- Statistics.BytesSent += (ulong)bytesSent;
-#endif
+
+ if (NetManager.EnableStatistics)
+ {
+ Statistics.PacketsSent++;
+ Statistics.BytesSent += (ulong)bytesSent;
+ }
+
_mergePos = 0;
_mergeCount = 0;
}
@@ -953,10 +999,13 @@ internal void SendUserData(NetPacket packet)
{
NetDebug.Write(NetLogLevel.Trace, "[P]SendingPacket: " + packet.Property);
int bytesSent = NetManager.SendRaw(packet, EndPoint);
-#if STATS_ENABLED
- Statistics.PacketsSent++;
- Statistics.BytesSent += (ulong)bytesSent;
-#endif
+
+ if (NetManager.EnableStatistics)
+ {
+ Statistics.PacketsSent++;
+ Statistics.BytesSent += (ulong)bytesSent;
+ }
+
return;
}
if (_mergePos + mergedPacketSize > _mtu)
@@ -984,13 +1033,24 @@ public void Flush()
currentChannel.SendNextPackets();
currentChannel = currentChannel.Next;
}
+
+ lock (_unreliableChannel)
+ {
+ while (_unreliableChannel.Count > 0)
+ {
+ NetPacket packet = _unreliableChannel.Dequeue();
+ SendUserData(packet);
+ NetManager.NetPacketPool.Recycle(packet);
+ }
+ }
+
SendMerged();
}
}
internal void Update(int deltaTime)
{
- _timeSinceLastPacket += deltaTime;
+ Interlocked.Add(ref _timeSinceLastPacket, deltaTime);
switch (_connectionState)
{
case ConnectionState.Connected:
@@ -1021,7 +1081,7 @@ internal void Update(int deltaTime)
}
return;
- case ConnectionState.Outcoming:
+ case ConnectionState.Outgoing:
_connectTimer += deltaTime;
if (_connectTimer > NetManager.ReconnectDelay)
{
@@ -1039,7 +1099,6 @@ internal void Update(int deltaTime)
return;
case ConnectionState.Disconnected:
- case ConnectionState.Incoming:
return;
}
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetSocket.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetSocket.cs
index 77b6aee..5815b1d 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetSocket.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetSocket.cs
@@ -1,7 +1,10 @@
-#if UNITY_4 || UNITY_5 || UNITY_5_3_OR_NEWER
+#if UNITY_5_3_OR_NEWER
#define UNITY
+#if UNITY_IOS && !UNITY_EDITOR
+using UnityEngine;
#endif
-#if NETSTANDARD2_0 || NETCOREAPP2_0
+#endif
+#if NETSTANDARD || NETCOREAPP
using System.Runtime.InteropServices;
#endif
@@ -12,6 +15,45 @@
namespace LiteNetLib
{
+#if UNITY_IOS && !UNITY_EDITOR
+ public class UnitySocketFix : MonoBehaviour
+ {
+ internal IPAddress BindAddrIPv4;
+ internal IPAddress BindAddrIPv6;
+ internal bool Reuse;
+ internal bool IPv6;
+ internal int Port;
+ internal bool Paused;
+ internal NetSocket Socket;
+
+ private void Update()
+ {
+ if (Socket == null)
+ Destroy(gameObject);
+ }
+
+ private void OnApplicationPause(bool pause)
+ {
+ if (Socket == null)
+ return;
+ if (pause)
+ {
+ Socket.Close(true);
+ Paused = true;
+ }
+ else if (Paused)
+ {
+ if (!Socket.Bind(BindAddrIPv4, BindAddrIPv6, Port, Reuse, IPv6))
+ {
+ NetDebug.WriteError("[S] Cannot restore connection \"{0}\",\"{1}\" port {2}", BindAddrIPv4, BindAddrIPv6, Port);
+ Socket.OnErrorRestore();
+ }
+ Paused = false;
+ }
+ }
+ }
+#endif
+
internal interface INetSocketListener
{
void OnMessageReceived(byte[] data, int length, SocketError errorCode, IPEndPoint remoteEndPoint);
@@ -19,18 +61,26 @@ internal interface INetSocketListener
internal sealed class NetSocket
{
- public const int ReceivePollingTime = 1000000; //1 second
+ public const int ReceivePollingTime = 500000; //0.5 second
private Socket _udpSocketv4;
private Socket _udpSocketv6;
private Thread _threadv4;
private Thread _threadv6;
- private volatile bool _running;
private readonly INetSocketListener _listener;
private const int SioUdpConnreset = -1744830452; //SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12
private static readonly IPAddress MulticastAddressV6 = IPAddress.Parse("FF02:0:0:0:0:0:0:1");
internal static readonly bool IPv6Support;
+#if UNITY_IOS && !UNITY_EDITOR
+ private UnitySocketFix _unitySocketFix;
+ public void OnErrorRestore()
+ {
+ Close(false);
+ _listener.OnMessageReceived(null, 0, SocketError.NotConnected, new IPEndPoint(0,0));
+ }
+#endif
public int LocalPort { get; private set; }
+ public volatile bool IsRunning;
public short Ttl
{
@@ -61,13 +111,23 @@ public NetSocket(INetSocketListener listener)
_listener = listener;
}
+ private bool IsActive()
+ {
+#if UNITY_IOS && !UNITY_EDITOR
+ var unitySocketFix = _unitySocketFix; //save for multithread
+ if (unitySocketFix != null && unitySocketFix.Paused)
+ return false;
+#endif
+ return IsRunning;
+ }
+
private void ReceiveLogic(object state)
{
Socket socket = (Socket)state;
EndPoint bufferEndPoint = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);
byte[] receiveBuffer = new byte[NetConstants.MaxPacketSize];
- while (_running)
+ while (IsActive())
{
int result;
@@ -83,6 +143,9 @@ private void ReceiveLogic(object state)
{
switch (ex.SocketErrorCode)
{
+#if UNITY_IOS && !UNITY_EDITOR
+ case SocketError.NotConnected:
+#endif
case SocketError.Interrupted:
case SocketError.NotSocket:
return;
@@ -90,15 +153,14 @@ private void ReceiveLogic(object state)
case SocketError.MessageSize:
case SocketError.TimedOut:
NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}",
- (int) ex.SocketErrorCode, ex.ToString());
+ (int)ex.SocketErrorCode, ex.ToString());
break;
default:
- NetDebug.WriteError("[R]Error code: {0} - {1}", (int) ex.SocketErrorCode,
+ NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode,
ex.ToString());
- _listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint) bufferEndPoint);
+ _listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint)bufferEndPoint);
break;
}
-
continue;
}
catch (ObjectDisposedException)
@@ -114,14 +176,34 @@ private void ReceiveLogic(object state)
public bool Bind(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool reuseAddress, bool ipv6)
{
+ if (IsActive())
+ return false;
+
_udpSocketv4 = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
if (!BindSocket(_udpSocketv4, new IPEndPoint(addressIPv4, port), reuseAddress))
return false;
- LocalPort = ((IPEndPoint) _udpSocketv4.LocalEndPoint).Port;
- _running = true;
- _threadv4 = new Thread(ReceiveLogic);
- _threadv4.Name = "SocketThreadv4(" + LocalPort + ")";
- _threadv4.IsBackground = true;
+#if UNITY_IOS && !UNITY_EDITOR
+ if (_unitySocketFix == null)
+ {
+ var unityFixObj = new GameObject("LiteNetLib_UnitySocketFix");
+ GameObject.DontDestroyOnLoad(unityFixObj);
+ _unitySocketFix = unityFixObj.AddComponent();
+ _unitySocketFix.Socket = this;
+ _unitySocketFix.BindAddrIPv4 = addressIPv4;
+ _unitySocketFix.BindAddrIPv6 = addressIPv6;
+ _unitySocketFix.Reuse = reuseAddress;
+ _unitySocketFix.Port = port;
+ _unitySocketFix.IPv6 = ipv6;
+ }
+#endif
+
+ LocalPort = ((IPEndPoint)_udpSocketv4.LocalEndPoint).Port;
+ IsRunning = true;
+ _threadv4 = new Thread(ReceiveLogic)
+ {
+ Name = "SocketThreadv4(" + LocalPort + ")",
+ IsBackground = true
+ };
_threadv4.Start(_udpSocketv4);
//Check IPv6 support
@@ -136,19 +218,21 @@ public bool Bind(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool re
{
#if !UNITY
_udpSocketv6.SetSocketOption(
- SocketOptionLevel.IPv6,
+ SocketOptionLevel.IPv6,
SocketOptionName.AddMembership,
new IPv6MulticastOption(MulticastAddressV6));
#endif
}
- catch(Exception)
+ catch (Exception)
{
// Unity3d throws exception - ignored
}
- _threadv6 = new Thread(ReceiveLogic);
- _threadv6.Name = "SocketThreadv6(" + LocalPort + ")";
- _threadv6.IsBackground = true;
+ _threadv6 = new Thread(ReceiveLogic)
+ {
+ Name = "SocketThreadv6(" + LocalPort + ")",
+ IsBackground = true
+ };
_threadv6.Start(_udpSocketv6);
}
@@ -162,14 +246,19 @@ private bool BindSocket(Socket socket, IPEndPoint ep, bool reuseAddress)
socket.SendTimeout = 500;
socket.ReceiveBufferSize = NetConstants.SocketBufferSize;
socket.SendBufferSize = NetConstants.SocketBufferSize;
+#if !UNITY || UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
+#if NETSTANDARD || NETCOREAPP
+ if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+#endif
try
{
- socket.IOControl(SioUdpConnreset, new byte[] {0}, null);
+ socket.IOControl(SioUdpConnreset, new byte[] { 0 }, null);
}
catch
{
//ignored
}
+#endif
try
{
@@ -184,7 +273,7 @@ private bool BindSocket(Socket socket, IPEndPoint ep, bool reuseAddress)
{
socket.Ttl = NetConstants.SocketTTL;
-#if NETSTANDARD2_0 || NETCOREAPP2_0
+#if NETSTANDARD || NETCOREAPP
if(!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
#endif
try { socket.DontFragment = true; }
@@ -219,9 +308,16 @@ private bool BindSocket(Socket socket, IPEndPoint ep, bool reuseAddress)
socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, true);
socket.Bind(ep);
}
+#if UNITY_2018_3_OR_NEWER
catch (SocketException ex)
{
+
+ //because its fixed in 2018_3
NetDebug.WriteError("[B]Bind exception: {0}, errorCode: {1}", ex.ToString(), ex.SocketErrorCode);
+#else
+ catch(SocketException)
+ {
+#endif
return false;
}
return true;
@@ -239,6 +335,8 @@ private bool BindSocket(Socket socket, IPEndPoint ep, bool reuseAddress)
public bool SendBroadcast(byte[] data, int offset, int size, int port)
{
+ if (!IsActive())
+ return false;
bool broadcastSuccess = false;
bool multicastSuccess = false;
try
@@ -249,7 +347,7 @@ public bool SendBroadcast(byte[] data, int offset, int size, int port)
size,
SocketFlags.None,
new IPEndPoint(IPAddress.Broadcast, port)) > 0;
-
+
if (_udpSocketv6 != null)
{
multicastSuccess = _udpSocketv6.SendTo(
@@ -270,6 +368,8 @@ public bool SendBroadcast(byte[] data, int offset, int size, int port)
public int SendTo(byte[] data, int offset, int size, IPEndPoint remoteEndPoint, ref SocketError errorCode)
{
+ if (!IsActive())
+ return 0;
try
{
var socket = _udpSocketv4;
@@ -291,7 +391,7 @@ public int SendTo(byte[] data, int offset, int size, IPEndPoint remoteEndPoint,
default:
NetDebug.WriteError("[S]" + ex);
break;
- }
+ }
errorCode = ex.SocketErrorCode;
return -1;
}
@@ -302,33 +402,30 @@ public int SendTo(byte[] data, int offset, int size, IPEndPoint remoteEndPoint,
}
}
- public void Close()
+ public void Close(bool suspend)
{
- _running = false;
- // first close sockets
- if (_udpSocketv4 != null)
+ if (!suspend)
{
- _udpSocketv4.Close();
- _udpSocketv4 = null;
+ IsRunning = false;
+#if UNITY_IOS && !UNITY_EDITOR
+ _unitySocketFix.Socket = null;
+ _unitySocketFix = null;
+#endif
}
+
+ if (_udpSocketv4 != null)
+ _udpSocketv4.Close();
if (_udpSocketv6 != null)
- {
_udpSocketv6.Close();
- _udpSocketv6 = null;
- }
- // then join threads
- if (_threadv4 != null)
- {
- if (_threadv4 != Thread.CurrentThread)
- _threadv4.Join();
- _threadv4 = null;
- }
- if (_threadv6 != null)
- {
- if (_threadv6 != Thread.CurrentThread)
- _threadv6.Join();
- _threadv6 = null;
- }
+ _udpSocketv4 = null;
+ _udpSocketv6 = null;
+
+ if (_threadv4 != null && _threadv4 != Thread.CurrentThread)
+ _threadv4.Join();
+ if (_threadv6 != null && _threadv6 != Thread.CurrentThread)
+ _threadv6.Join();
+ _threadv4 = null;
+ _threadv6 = null;
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetUtils.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetUtils.cs
index 39db291..b99cfc3 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetUtils.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/NetUtils.cs
@@ -61,7 +61,7 @@ private static IPAddress ResolveAddress(string hostStr, AddressFamily addressFam
private static IPAddress[] ResolveAddresses(string hostStr)
{
-#if NETSTANDARD2_0 || NETCOREAPP2_0
+#if NETSTANDARD || NETCOREAPP
var hostTask = Dns.GetHostEntryAsync(hostStr);
hostTask.GetAwaiter().GetResult();
var host = hostTask.Result;
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/ReliableChannel.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/ReliableChannel.cs
index 0634e80..77f24ca 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/ReliableChannel.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/ReliableChannel.cs
@@ -62,6 +62,7 @@ public bool Clear(NetPeer peer)
private bool _mustSendAcks;
+ private readonly DeliveryMethod _deliveryMethod;
private readonly bool _ordered;
private readonly int _windowSize;
private const int BitsInByte = 8;
@@ -77,9 +78,15 @@ public ReliableChannel(NetPeer peer, bool ordered, byte id) : base(peer)
_pendingPackets[i] = new PendingPacket();
if (_ordered)
+ {
+ _deliveryMethod = DeliveryMethod.ReliableOrdered;
_receivedPackets = new NetPacket[_windowSize];
+ }
else
+ {
+ _deliveryMethod = DeliveryMethod.ReliableUnordered;
_earlyReceived = new bool[_windowSize];
+ }
_localWindowStart = 0;
_localSeqence = 0;
@@ -131,9 +138,15 @@ private void ProcessAck(NetPacket packet)
int currentBit = pendingIdx % BitsInByte;
if ((acksData[currentByte] & (1 << currentBit)) == 0)
{
-#if STATS_ENABLED || DEBUG
- Peer.Statistics.PacketLoss++;
+#if DEBUG
+ Peer.Statistics.PacketLoss++;
+#else
+ if (Peer.NetManager.EnableStatistics)
+ {
+ Peer.Statistics.PacketLoss++;
+ }
#endif
+
//Skip false ack
NetDebug.Write("[PA]False ack: {0}", pendingSeq);
continue;
@@ -268,7 +281,7 @@ public override bool ProcessPacket(NetPacket packet)
if (seq == _remoteSequence)
{
NetDebug.Write("[RR]ReliableInOrder packet succes");
- Peer.AddIncomingPacket(packet);
+ Peer.AddReliablePacket(_deliveryMethod, packet);
_remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence;
if (_ordered)
@@ -278,7 +291,7 @@ public override bool ProcessPacket(NetPacket packet)
{
//process holded packet
_receivedPackets[_remoteSequence % _windowSize] = null;
- Peer.AddIncomingPacket(p);
+ Peer.AddReliablePacket(_deliveryMethod, p);
_remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence;
}
}
@@ -302,7 +315,7 @@ public override bool ProcessPacket(NetPacket packet)
else
{
_earlyReceived[ackIdx] = true;
- Peer.AddIncomingPacket(packet);
+ Peer.AddReliablePacket(_deliveryMethod, packet);
}
return true;
}
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/SequencedChannel.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/SequencedChannel.cs
index 0cc6793..c5e3897 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/SequencedChannel.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/SequencedChannel.cs
@@ -1,3 +1,5 @@
+using System;
+
namespace LiteNetLib
{
internal sealed class SequencedChannel : BaseChannel
@@ -9,6 +11,7 @@ internal sealed class SequencedChannel : BaseChannel
private readonly NetPacket _ackPacket;
private bool _mustSendAck;
private readonly byte _id;
+ private long _lastPacketSendTime;
public SequencedChannel(NetPeer peer, bool reliable, byte id) : base(peer)
{
@@ -22,9 +25,16 @@ public override void SendNextPackets()
{
if (_reliable && OutgoingQueue.Count == 0)
{
+ long currentTime = DateTime.UtcNow.Ticks;
+ long packetHoldTime = currentTime - _lastPacketSendTime;
+ if (packetHoldTime < Peer.ResendDelay * TimeSpan.TicksPerMillisecond)
+ return;
var packet = _lastPacket;
- if(packet != null)
+ if (packet != null)
+ {
+ _lastPacketSendTime = currentTime;
Peer.SendUserData(packet);
+ }
}
else
{
@@ -39,9 +49,14 @@ public override void SendNextPackets()
Peer.SendUserData(packet);
if (_reliable && OutgoingQueue.Count == 0)
+ {
+ _lastPacketSendTime = DateTime.UtcNow.Ticks;
_lastPacket = packet;
+ }
else
+ {
Peer.NetManager.NetPacketPool.Recycle(packet);
+ }
}
}
}
@@ -56,6 +71,8 @@ public override void SendNextPackets()
public override bool ProcessPacket(NetPacket packet)
{
+ if (packet.IsFragmented)
+ return false;
if (packet.Property == PacketProperty.Ack)
{
if (_reliable && _lastPacket != null && packet.Sequence == _lastPacket.Sequence)
@@ -68,7 +85,10 @@ public override bool ProcessPacket(NetPacket packet)
{
Peer.Statistics.PacketLoss += (ulong)(relative - 1);
_remoteSequence = packet.Sequence;
- Peer.AddIncomingPacket(packet);
+ Peer.NetManager.CreateReceiveEvent(
+ packet,
+ _reliable ? DeliveryMethod.ReliableSequenced : DeliveryMethod.Sequenced,
+ Peer);
packetProcessed = true;
}
_mustSendAck = true;
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/SimpleChannel.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/SimpleChannel.cs
deleted file mode 100644
index eb9c862..0000000
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/SimpleChannel.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace LiteNetLib
-{
- internal sealed class SimpleChannel : BaseChannel
- {
- public SimpleChannel(NetPeer peer) : base(peer)
- {
-
- }
-
- public override void SendNextPackets()
- {
- lock (OutgoingQueue)
- {
- while (OutgoingQueue.Count > 0)
- {
- NetPacket packet = OutgoingQueue.Dequeue();
- Peer.SendUserData(packet);
- Peer.NetManager.NetPacketPool.Recycle(packet);
- }
- }
- }
-
- public override bool ProcessPacket(NetPacket packet)
- {
- return false;
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/CRC32C.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/CRC32C.cs
new file mode 100644
index 0000000..5674d3e
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/CRC32C.cs
@@ -0,0 +1,102 @@
+#if NETCOREAPP3_0
+using System;
+using System.Runtime.Intrinsics.X86;
+#endif
+
+namespace LiteNetLib.Utils
+{
+ //Implemenatation from Crc32.NET
+ public static class CRC32C
+ {
+#if NETCOREAPP3_0
+ private static readonly bool _x64Available;
+ private static readonly bool _sseAvailable;
+#endif
+ public const int ChecksumSize = 4;
+ private const uint Poly = 0x82F63B78u;
+ private static readonly uint[] Table;
+
+ static CRC32C()
+ {
+#if NETCOREAPP3_0
+ _sseAvailable = Sse42.IsSupported;
+ _x64Available = Sse42.X64.IsSupported;
+ if(_sseAvailable)
+ return;
+#endif
+ Table = new uint[16 * 256];
+ for (uint i = 0; i < 256; i++)
+ {
+ uint res = i;
+ for (int t = 0; t < 16; t++)
+ {
+ for (int k = 0; k < 8; k++)
+ res = (res & 1) == 1 ? Poly ^ (res >> 1) : (res >> 1);
+ Table[t * 256 + i] = res;
+ }
+ }
+ }
+
+ ///
+ /// Compute CRC32C for data
+ ///
+ /// input data
+ /// offset
+ /// length
+ /// CRC32C checksum
+ public static uint Compute(byte[] input, int offset, int length)
+ {
+ uint crcLocal = uint.MaxValue;
+#if NETCOREAPP3_0
+ if(_sseAvailable)
+ {
+ if (_x64Available)
+ {
+ while (length >= 8)
+ {
+ crcLocal = (uint)Sse42.X64.Crc32(crcLocal, BitConverter.ToUInt64(input, offset));
+ offset += 8;
+ length -= 8;
+ }
+ }
+ while (length > 0)
+ {
+ crcLocal = Sse42.Crc32(crcLocal, input[offset]);
+ offset++;
+ length--;
+ }
+ return crcLocal ^ uint.MaxValue;
+ }
+#endif
+ while (length >= 16)
+ {
+ var a = Table[(3 * 256) + input[offset + 12]]
+ ^ Table[(2 * 256) + input[offset + 13]]
+ ^ Table[(1 * 256) + input[offset + 14]]
+ ^ Table[(0 * 256) + input[offset + 15]];
+
+ var b = Table[(7 * 256) + input[offset + 8]]
+ ^ Table[(6 * 256) + input[offset + 9]]
+ ^ Table[(5 * 256) + input[offset + 10]]
+ ^ Table[(4 * 256) + input[offset + 11]];
+
+ var c = Table[(11 * 256) + input[offset + 4]]
+ ^ Table[(10 * 256) + input[offset + 5]]
+ ^ Table[(9 * 256) + input[offset + 6]]
+ ^ Table[(8 * 256) + input[offset + 7]];
+
+ var d = Table[(15 * 256) + ((byte)crcLocal ^ input[offset])]
+ ^ Table[(14 * 256) + ((byte)(crcLocal >> 8) ^ input[offset + 1])]
+ ^ Table[(13 * 256) + ((byte)(crcLocal >> 16) ^ input[offset + 2])]
+ ^ Table[(12 * 256) + ((crcLocal >> 24) ^ input[offset + 3])];
+
+ crcLocal = d ^ c ^ b ^ a;
+ offset += 16;
+ length -= 16;
+ }
+ while (--length >= 0)
+ crcLocal = Table[(byte)(crcLocal ^ input[offset++])] ^ crcLocal >> 8;
+ return crcLocal ^ uint.MaxValue;
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkAnimatorEditor.cs.meta b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/CRC32C.cs.meta
similarity index 83%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkAnimatorEditor.cs.meta
rename to LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/CRC32C.cs.meta
index 1b537bc..3c0022d 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkAnimatorEditor.cs.meta
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/CRC32C.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 9589e903d4e98490fb1157762a307fd7
+guid: e017b5288ddedcd4d853a2cdb0d4a086
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetDataReader.cs
index f31e6f8..2570358 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetDataReader.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetDataReader.cs
@@ -135,10 +135,8 @@ public bool[] GetBoolArray()
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new bool[size];
- for (int i = 0; i < size; i++)
- {
- arr[i] = GetBool();
- }
+ Buffer.BlockCopy(_data, _position, arr, 0, size);
+ _position += size;
return arr;
}
@@ -147,10 +145,8 @@ public ushort[] GetUShortArray()
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new ushort[size];
- for (int i = 0; i < size; i++)
- {
- arr[i] = GetUShort();
- }
+ Buffer.BlockCopy(_data, _position, arr, 0, size * 2);
+ _position += size * 2;
return arr;
}
@@ -159,10 +155,8 @@ public short[] GetShortArray()
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new short[size];
- for (int i = 0; i < size; i++)
- {
- arr[i] = GetShort();
- }
+ Buffer.BlockCopy(_data, _position, arr, 0, size * 2);
+ _position += size * 2;
return arr;
}
@@ -171,10 +165,8 @@ public long[] GetLongArray()
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new long[size];
- for (int i = 0; i < size; i++)
- {
- arr[i] = GetLong();
- }
+ Buffer.BlockCopy(_data, _position, arr, 0, size * 8);
+ _position += size * 8;
return arr;
}
@@ -183,10 +175,8 @@ public ulong[] GetULongArray()
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new ulong[size];
- for (int i = 0; i < size; i++)
- {
- arr[i] = GetULong();
- }
+ Buffer.BlockCopy(_data, _position, arr, 0, size * 8);
+ _position += size * 8;
return arr;
}
@@ -195,10 +185,8 @@ public int[] GetIntArray()
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new int[size];
- for (int i = 0; i < size; i++)
- {
- arr[i] = GetInt();
- }
+ Buffer.BlockCopy(_data, _position, arr, 0, size * 4);
+ _position += size * 4;
return arr;
}
@@ -207,10 +195,8 @@ public uint[] GetUIntArray()
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new uint[size];
- for (int i = 0; i < size; i++)
- {
- arr[i] = GetUInt();
- }
+ Buffer.BlockCopy(_data, _position, arr, 0, size * 4);
+ _position += size * 4;
return arr;
}
@@ -219,10 +205,8 @@ public float[] GetFloatArray()
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new float[size];
- for (int i = 0; i < size; i++)
- {
- arr[i] = GetFloat();
- }
+ Buffer.BlockCopy(_data, _position, arr, 0, size * 4);
+ _position += size * 4;
return arr;
}
@@ -231,10 +215,8 @@ public double[] GetDoubleArray()
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new double[size];
- for (int i = 0; i < size; i++)
- {
- arr[i] = GetDouble();
- }
+ Buffer.BlockCopy(_data, _position, arr, 0, size * 8);
+ _position += size * 8;
return arr;
}
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetDataWriter.cs
index 27268cb..4f4f855 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetDataWriter.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetDataWriter.cs
@@ -253,94 +253,61 @@ public void Put(bool value)
_position++;
}
- public void PutArray(float[] value)
+ private void PutArray(Array arr, int sz)
{
- ushort len = value == null ? (ushort)0 : (ushort)value.Length;
+ ushort length = arr == null ? (ushort) 0 : (ushort)arr.Length;
+ sz *= length;
if (_autoResize)
- ResizeIfNeed(_position + len * 4 + 2);
- Put(len);
- for (int i = 0; i < len; i++)
- Put(value[i]);
+ ResizeIfNeed(_position + sz + 2);
+ FastBitConverter.GetBytes(_data, _position, length);
+ if (arr != null)
+ Buffer.BlockCopy(arr, 0, _data, _position + 2, sz);
+ _position += sz + 2;
+ }
+
+ public void PutArray(float[] value)
+ {
+ PutArray(value, 4);
}
public void PutArray(double[] value)
{
- ushort len = value == null ? (ushort)0 : (ushort)value.Length;
- if (_autoResize)
- ResizeIfNeed(_position + len * 8 + 2);
- Put(len);
- for (int i = 0; i < len; i++)
- Put(value[i]);
+ PutArray(value, 8);
}
public void PutArray(long[] value)
{
- ushort len = value == null ? (ushort)0 : (ushort)value.Length;
- if (_autoResize)
- ResizeIfNeed(_position + len * 8 + 2);
- Put(len);
- for (int i = 0; i < len; i++)
- Put(value[i]);
+ PutArray(value, 8);
}
public void PutArray(ulong[] value)
{
- ushort len = value == null ? (ushort)0 : (ushort)value.Length;
- if (_autoResize)
- ResizeIfNeed(_position + len * 8 + 2);
- Put(len);
- for (int i = 0; i < len; i++)
- Put(value[i]);
+ PutArray(value, 8);
}
public void PutArray(int[] value)
{
- ushort len = value == null ? (ushort)0 : (ushort)value.Length;
- if (_autoResize)
- ResizeIfNeed(_position + len * 4 + 2);
- Put(len);
- for (int i = 0; i < len; i++)
- Put(value[i]);
+ PutArray(value, 4);
}
public void PutArray(uint[] value)
{
- ushort len = value == null ? (ushort)0 : (ushort)value.Length;
- if (_autoResize)
- ResizeIfNeed(_position + len * 4 + 2);
- Put(len);
- for (int i = 0; i < len; i++)
- Put(value[i]);
+ PutArray(value, 4);
}
public void PutArray(ushort[] value)
{
- ushort len = value == null ? (ushort)0 : (ushort)value.Length;
- if (_autoResize)
- ResizeIfNeed(_position + len * 2 + 2);
- Put(len);
- for (int i = 0; i < len; i++)
- Put(value[i]);
+ PutArray(value, 2);
}
public void PutArray(short[] value)
{
- ushort len = value == null ? (ushort)0 : (ushort)value.Length;
- if (_autoResize)
- ResizeIfNeed(_position + len * 2 + 2);
- Put(len);
- for (int i = 0; i < len; i++)
- Put(value[i]);
+ PutArray(value, 2);
}
public void PutArray(bool[] value)
{
- ushort len = value == null ? (ushort)0 : (ushort)value.Length;
- if (_autoResize)
- ResizeIfNeed(_position + len + 2);
- Put(len);
- for (int i = 0; i < len; i++)
- Put(value[i]);
+ PutArray(value, 1);
}
public void PutArray(string[] value)
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetPacketProcessor.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetPacketProcessor.cs
index f5a7844..b8304a5 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetPacketProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetPacketProcessor.cs
@@ -64,10 +64,9 @@ protected virtual void WriteHash(NetDataWriter writer)
/// Register nested property type
///
/// INetSerializable structure
- /// True - if register successful, false - if type already registered
- public bool RegisterNestedType() where T : struct, INetSerializable
+ public void RegisterNestedType() where T : struct, INetSerializable
{
- return _netSerializer.RegisterNestedType();
+ _netSerializer.RegisterNestedType();
}
///
@@ -75,20 +74,18 @@ public bool RegisterNestedType() where T : struct, INetSerializable
///
///
///
- /// True - if register successful, false - if type already registered
- public bool RegisterNestedType(Action writeDelegate, Func readDelegate)
+ public void RegisterNestedType(Action writeDelegate, Func readDelegate)
{
- return _netSerializer.RegisterNestedType(writeDelegate, readDelegate);
+ _netSerializer.RegisterNestedType(writeDelegate, readDelegate);
}
///
/// Register nested property type
///
/// INetSerializable class
- /// True - if register successful, false - if type already registered
- public bool RegisterNestedType(Func constructor) where T : class, INetSerializable
+ public void RegisterNestedType(Func constructor) where T : class, INetSerializable
{
- return _netSerializer.RegisterNestedType(constructor);
+ _netSerializer.RegisterNestedType(constructor);
}
///
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetSerializer.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetSerializer.cs
index 3a61fc6..42e401a 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetSerializer.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NetSerializer.cs
@@ -7,247 +7,439 @@ namespace LiteNetLib.Utils
{
public class InvalidTypeException : ArgumentException
{
- public InvalidTypeException()
+ public InvalidTypeException(string message) : base(message) { }
+ }
+
+ public class ParseException : Exception
+ {
+ public ParseException(string message) : base(message) { }
+ }
+
+ public class NetSerializer
+ {
+ private abstract class FastCall
+ {
+ public bool IsArray;
+ public virtual void Init(MethodInfo getMethod, MethodInfo setMethod, bool isArray) { IsArray = isArray; }
+ public abstract void Read(T inf, NetDataReader r);
+ public abstract void Write(T inf, NetDataWriter w);
+ public virtual void ReadArray(T inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: " + typeof(T) + "[]"); }
+ public virtual void WriteArray(T inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: " + typeof(T) + "[]"); }
+ }
+
+ private abstract class FastCallSpecific : FastCall
+ {
+ protected Func Getter;
+ protected Action Setter;
+ protected Func GetterArr;
+ protected Action SetterArr;
+
+ protected TProperty[] ReadArrayHelper(TClass inf, NetDataReader r)
+ {
+ ushort count = r.GetUShort();
+ var arr = GetterArr(inf);
+ return arr == null || arr.Length != count ? new TProperty[count] : arr;
+ }
+
+ protected TProperty[] WriteArrayHelper(TClass inf, NetDataWriter w)
+ {
+ var arr = GetterArr(inf);
+ w.Put((ushort)arr.Length);
+ return arr;
+ }
+
+ public override void Init(MethodInfo getMethod, MethodInfo setMethod, bool isArray)
+ {
+ base.Init(getMethod, setMethod, isArray);
+ if (IsArray)
+ {
+ GetterArr = (Func)Delegate.CreateDelegate(typeof(Func), getMethod);
+ SetterArr = (Action)Delegate.CreateDelegate(typeof(Action), setMethod);
+ }
+ else
+ {
+ Getter = (Func)Delegate.CreateDelegate(typeof(Func), getMethod);
+ Setter = (Action)Delegate.CreateDelegate(typeof(Action), setMethod);
+ }
+ }
+ }
+
+ private abstract class FastCallSpecificAuto : FastCallSpecific
+ {
+ protected abstract void ElementRead(NetDataReader r, out TProperty prop);
+ protected abstract void ElementWrite(NetDataWriter w, ref TProperty prop);
+
+ public override void Read(TClass inf, NetDataReader r)
+ {
+ TProperty elem;
+ ElementRead(r, out elem);
+ Setter(inf, elem);
+ }
+
+ public override void Write(TClass inf, NetDataWriter w)
+ {
+ var elem = Getter(inf);
+ ElementWrite(w, ref elem);
+ }
+
+ public override void ReadArray(TClass inf, NetDataReader r)
+ {
+ var arr = ReadArrayHelper(inf, r);
+ for (int i = 0; i < arr.Length; i++)
+ ElementRead(r, out arr[i]);
+ SetterArr(inf, arr);
+ }
+
+ public override void WriteArray(TClass inf, NetDataWriter w)
+ {
+ var arr = WriteArrayHelper(inf, w);
+ for (int i = 0; i < arr.Length; i++)
+ ElementWrite(w, ref arr[i]);
+ }
+ }
+
+ private sealed class FastCallStatic : FastCallSpecific
+ {
+ private readonly Action _writer;
+ private readonly Func _reader;
+
+ public FastCallStatic(Action write, Func read)
+ {
+ _writer = write;
+ _reader = read;
+ }
+
+ public override void Read(TClass inf, NetDataReader r) { Setter(inf, _reader(r)); }
+ public override void Write(TClass inf, NetDataWriter w) { _writer(w, Getter(inf)); }
+
+ public override void ReadArray(TClass inf, NetDataReader r)
+ {
+ var arr = ReadArrayHelper(inf, r);
+ int len = arr.Length;
+ for (int i = 0; i < len; i++)
+ arr[i] = _reader(r);
+ SetterArr(inf, arr);
+ }
+
+ public override void WriteArray(TClass inf, NetDataWriter w)
+ {
+ var arr = WriteArrayHelper(inf, w);
+ int len = arr.Length;
+ for (int i = 0; i < len; i++)
+ _writer(w, arr[i]);
+ }
+ }
+
+ private sealed class FastCallStruct : FastCallSpecific where TProperty : struct, INetSerializable
+ {
+ private TProperty _p;
+
+ public override void Read(TClass inf, NetDataReader r)
+ {
+ _p.Deserialize(r);
+ Setter(inf, _p);
+ }
+
+ public override void Write(TClass inf, NetDataWriter w)
+ {
+ _p = Getter(inf);
+ _p.Serialize(w);
+ }
+
+ public override void ReadArray(TClass inf, NetDataReader r)
+ {
+ var arr = ReadArrayHelper(inf, r);
+ int len = arr.Length;
+ for (int i = 0; i < len; i++)
+ arr[i].Deserialize(r);
+ SetterArr(inf, arr);
+ }
+
+ public override void WriteArray(TClass inf, NetDataWriter w)
+ {
+ var arr = WriteArrayHelper(inf, w);
+ int len = arr.Length;
+ for (int i = 0; i < len; i++)
+ arr[i].Serialize(w);
+ }
+ }
+
+ private sealed class FastCallClass : FastCallSpecific where TProperty : class, INetSerializable
+ {
+ private readonly Func _constructor;
+ public FastCallClass(Func constructor) { _constructor = constructor; }
+
+ public override void Read(TClass inf, NetDataReader r)
+ {
+ var p = _constructor();
+ p.Deserialize(r);
+ Setter(inf, p);
+ }
+
+ public override void Write(TClass inf, NetDataWriter w)
+ {
+ var p = Getter(inf);
+ if(p != null)
+ p.Serialize(w);
+ }
+
+ public override void ReadArray(TClass inf, NetDataReader r)
+ {
+ var arr = ReadArrayHelper(inf, r);
+ int len = arr.Length;
+ for (int i = 0; i < len; i++)
+ {
+ arr[i] = _constructor();
+ arr[i].Deserialize(r);
+ }
+ SetterArr(inf, arr);
+ }
+
+ public override void WriteArray(TClass inf, NetDataWriter w)
+ {
+ var arr = WriteArrayHelper(inf, w);
+ int len = arr.Length;
+ for (int i = 0; i < len; i++)
+ arr[i].Serialize(w);
+ }
+ }
+
+ private class IntSerializer : FastCallSpecific
{
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetInt()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetIntArray()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
- public InvalidTypeException(string message) : base(message)
+ private class UIntSerializer : FastCallSpecific
{
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetUInt()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetUIntArray()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
- public InvalidTypeException(string message, Exception innerException) : base(message, innerException)
+ private class ShortSerializer : FastCallSpecific
{
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetShort()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetShortArray()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
- public InvalidTypeException(string message, string paramName) : base(message, paramName)
+ private class UShortSerializer : FastCallSpecific
{
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetUShort()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetUShortArray()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
- public InvalidTypeException(string message, string paramName, Exception innerException) : base(message, paramName, innerException)
+ private class LongSerializer : FastCallSpecific
{
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetLong()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetLongArray()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
- }
- public class ParseException : Exception
- {
- public ParseException()
+ private class ULongSerializer : FastCallSpecific
{
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetULong()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetULongArray()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
- public ParseException(string message) : base(message)
+ private class ByteSerializer : FastCallSpecific
{
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetByte()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetBytesWithLength()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutBytesWithLength(GetterArr(inf)); }
}
- public ParseException(string message, Exception innerException) : base(message, innerException)
+ private class SByteSerializer : FastCallSpecific
{
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetSByte()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetSBytesWithLength()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutSBytesWithLength(GetterArr(inf)); }
}
- }
-
- public sealed class NetSerializer
- {
- private sealed class NestedType
+
+ private class FloatSerializer : FastCallSpecific
+ {
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetFloat()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetFloatArray()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
+ }
+
+ private class DoubleSerializer : FastCallSpecific
{
- public readonly NestedTypeWriter WriteDelegate;
- public readonly NestedTypeReader ReadDelegate;
- public readonly NestedTypeWriter ArrayWriter;
- public readonly NestedTypeReader ArrayReader;
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetDouble()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetDoubleArray()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
+ }
+
+ private class BoolSerializer : FastCallSpecific
+ {
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetBool()); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetBoolArray()); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
+ }
+
+ private class CharSerializer : FastCallSpecificAuto
+ {
+ protected override void ElementWrite(NetDataWriter w, ref char prop) { w.Put(prop); }
+ protected override void ElementRead(NetDataReader r, out char prop) { prop = r.GetChar(); }
+ }
+
+ private class IPEndPointSerializer : FastCallSpecificAuto
+ {
+ protected override void ElementWrite(NetDataWriter w, ref IPEndPoint prop) { w.Put(prop); }
+ protected override void ElementRead(NetDataReader r, out IPEndPoint prop) { prop = r.GetNetEndPoint(); }
+ }
+
+ private class StringSerializer : FastCallSpecific
+ {
+ private readonly int _maxLength;
+ public StringSerializer(int maxLength) { _maxLength = maxLength > 0 ? maxLength : short.MaxValue; }
+ public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetString(_maxLength)); }
+ public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf), _maxLength); }
+ public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetStringArray(_maxLength)); }
+ public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf), _maxLength); }
+ }
- public NestedType(NestedTypeWriter writeDelegate, NestedTypeReader readDelegate, NestedTypeWriter arrayWriter, NestedTypeReader arrayReader)
+ private class EnumByteSerializer : FastCall
+ {
+ protected readonly PropertyInfo Property;
+ protected readonly Type PropertyType;
+ public EnumByteSerializer(PropertyInfo property, Type propertyType)
{
- WriteDelegate = writeDelegate;
- ReadDelegate = readDelegate;
- ArrayWriter = arrayWriter;
- ArrayReader = arrayReader;
+ Property = property;
+ PropertyType = propertyType;
}
+ public override void Read(T inf, NetDataReader r) { Property.SetValue(inf, Enum.ToObject(PropertyType, r.GetByte()), null); }
+ public override void Write(T inf, NetDataWriter w) { w.Put((byte)Property.GetValue(inf, null)); }
}
- private delegate void NestedTypeWriter(NetDataWriter writer, object customObj);
- private delegate object NestedTypeReader(NetDataReader reader);
+ private class EnumIntSerializer : EnumByteSerializer
+ {
+ public EnumIntSerializer(PropertyInfo property, Type propertyType) : base(property, propertyType) { }
+ public override void Read(T inf, NetDataReader r) { Property.SetValue(inf, Enum.ToObject(PropertyType, r.GetInt()), null); }
+ public override void Write(T inf, NetDataWriter w) { w.Put((int)Property.GetValue(inf, null)); }
+ }
private sealed class ClassInfo
{
public static ClassInfo Instance;
- private readonly Action[] _writeDelegate;
- private readonly Action[] _readDelegate;
+ private readonly FastCall[] _serializers;
private readonly int _membersCount;
- public ClassInfo(List> readDelegates, List> writeDelegates)
+ public ClassInfo(List> serializers)
{
- _membersCount = readDelegates.Count;
- _writeDelegate = writeDelegates.ToArray();
- _readDelegate = readDelegates.ToArray();
+ _membersCount = serializers.Count;
+ _serializers = serializers.ToArray();
}
public void Write(T obj, NetDataWriter writer)
{
for (int i = 0; i < _membersCount; i++)
- _writeDelegate[i](obj, writer);
+ {
+ var s = _serializers[i];
+ if (s.IsArray)
+ s.WriteArray(obj, writer);
+ else
+ s.Write(obj, writer);
+ }
}
public void Read(T obj, NetDataReader reader)
{
for (int i = 0; i < _membersCount; i++)
- _readDelegate[i](obj, reader);
+ {
+ var s = _serializers[i];
+ if (s.IsArray)
+ s.ReadArray(obj, reader);
+ else
+ s.Read(obj, reader);
+ }
}
}
- private static readonly HashSet BasicTypes = new HashSet
- {
- typeof(int),
- typeof(uint),
- typeof(byte),
- typeof(sbyte),
- typeof(short),
- typeof(ushort),
- typeof(long),
- typeof(ulong),
- typeof(string),
- typeof(float),
- typeof(double),
- typeof(bool),
- typeof(char),
- typeof(IPEndPoint)
- };
-
- private readonly NetDataWriter _writer;
- private readonly int _maxStringLength;
- private readonly Dictionary _registeredNestedTypes;
+ private abstract class CustomType
+ {
+ public abstract FastCall Get();
+ }
- public NetSerializer() : this(0)
+ private sealed class CustomTypeStruct : CustomType where TProperty : struct, INetSerializable
{
-
+ public override FastCall Get() { return new FastCallStruct(); }
}
- public NetSerializer(int maxStringLength)
+ private sealed class CustomTypeClass : CustomType where TProperty : class, INetSerializable
{
- _maxStringLength = maxStringLength;
- _registeredNestedTypes = new Dictionary();
- _writer = new NetDataWriter();
+ private readonly Func _constructor;
+ public CustomTypeClass(Func constructor) { _constructor = constructor; }
+ public override FastCall Get() { return new FastCallClass(_constructor); }
}
- private bool RegisterNestedTypeInternal(Func constructor) where T : INetSerializable
+ private sealed class CustomTypeStatic : CustomType
{
- var t = typeof(T);
- if (_registeredNestedTypes.ContainsKey(t))
- return false;
- NestedType nestedType;
- NestedTypeWriter nestedTypeWriter = (writer, obj) => ((T) obj).Serialize(writer);
- NestedTypeWriter nestedTypeArrayWriter = (writer, arr) =>
- {
- var typedArr = (T[]) arr;
- writer.Put((ushort) typedArr.Length);
- for (int i = 0; i < typedArr.Length; i++)
- typedArr[i].Serialize(writer);
- };
-
- //struct
- if (constructor == null)
+ private readonly Action _writer;
+ private readonly Func _reader;
+ public CustomTypeStatic(Action writer, Func reader)
{
- nestedType = new NestedType(
- nestedTypeWriter,
- reader =>
- {
- var instance = default(T);
- instance.Deserialize(reader);
- return instance;
- },
- nestedTypeArrayWriter,
- reader =>
- {
- var typedArr = new T[reader.GetUShort()];
- for (int i = 0; i < typedArr.Length; i++)
- typedArr[i].Deserialize(reader);
- return typedArr;
- });
+ _writer = writer;
+ _reader = reader;
}
- else //class
- {
- nestedType = new NestedType(
- nestedTypeWriter,
- reader =>
- {
- var instance = constructor();
- instance.Deserialize(reader);
- return instance;
- },
- nestedTypeArrayWriter,
- reader =>
- {
- var typedArr = new T[reader.GetUShort()];
- for (int i = 0; i < typedArr.Length; i++)
- {
- typedArr[i] = constructor();
- typedArr[i].Deserialize(reader);
- }
- return typedArr;
- });
- }
- _registeredNestedTypes.Add(t, nestedType);
- return true;
+ public override FastCall Get() { return new FastCallStatic(_writer, _reader); }
}
///
- /// Register nested property type
+ /// Register custom property type
///
/// INetSerializable structure
- /// True - if register successful, false - if type already registered
- public bool RegisterNestedType() where T : struct, INetSerializable
+ public void RegisterNestedType() where T : struct, INetSerializable
{
- return RegisterNestedTypeInternal(null);
+ _registeredTypes.Add(typeof(T), new CustomTypeStruct());
}
///
- /// Register nested property type
+ /// Register custom property type
///
/// INetSerializable class
- /// True - if register successful, false - if type already registered
- public bool RegisterNestedType(Func constructor) where T : class, INetSerializable
+ public void RegisterNestedType(Func constructor) where T : class, INetSerializable
{
- return RegisterNestedTypeInternal(constructor);
+ _registeredTypes.Add(typeof(T), new CustomTypeClass(constructor));
}
///
- /// Register nested property type
+ /// Register custom property type
///
- ///
- ///
- /// True - if register successful, false - if type already registered
- public bool RegisterNestedType(Action writeDelegate, Func readDelegate)
+ /// Any packet
+ /// custom type writer
+ /// custom type reader
+ public void RegisterNestedType(Action writer, Func reader)
{
- var t = typeof(T);
- if (BasicTypes.Contains(t) || _registeredNestedTypes.ContainsKey(t))
- return false;
-
- var rwDelegates = new NestedType(
- (writer, obj) => writeDelegate(writer, (T)obj),
- reader => readDelegate(reader),
- (writer, arr) =>
- {
- var typedArr = (T[])arr;
- writer.Put((ushort)typedArr.Length);
- for (int i = 0; i < typedArr.Length; i++)
- writeDelegate(writer, typedArr[i]);
- },
- reader =>
- {
- var typedArr = new T[reader.GetUShort()];
- for (int i = 0; i < typedArr.Length; i++)
- typedArr[i] = readDelegate(reader);
- return typedArr;
- });
-
- _registeredNestedTypes.Add(t, rwDelegates);
- return true;
+ _registeredTypes.Add(typeof(T), new CustomTypeStatic(writer, reader));
}
- private static Func ExtractGetDelegate(MethodInfo info)
+ private NetDataWriter _writer;
+ private readonly int _maxStringLength;
+ private readonly Dictionary _registeredTypes = new Dictionary();
+
+ public NetSerializer() : this(0)
{
- return (Func)Delegate.CreateDelegate(typeof(Func), info);
}
- private static Action ExtractSetDelegate(MethodInfo info)
+ public NetSerializer(int maxStringLength)
{
- return (Action)Delegate.CreateDelegate(typeof(Action), info);
+ _maxStringLength = maxStringLength;
}
private ClassInfo RegisterInternal()
@@ -261,271 +453,75 @@ private ClassInfo RegisterInternal()
BindingFlags.Public |
BindingFlags.GetProperty |
BindingFlags.SetProperty);
- var writeDelegates = new List>();
- var readDelegates = new List>();
+ var serializers = new List>();
for (int i = 0; i < props.Length; i++)
{
var property = props[i];
var propertyType = property.PropertyType;
- bool isEnum = propertyType.IsEnum;
+ var elementType = propertyType.IsArray ? propertyType.GetElementType() : propertyType;
var getMethod = property.GetGetMethod();
var setMethod = property.GetSetMethod();
if (getMethod == null || setMethod == null)
continue;
-
- if (isEnum)
+
+ FastCall serialzer = null;
+ if (propertyType.IsEnum)
{
var underlyingType = Enum.GetUnderlyingType(propertyType);
if (underlyingType == typeof(byte))
- {
- readDelegates.Add((inf, r) =>
- {
- property.SetValue(inf, Enum.ToObject(propertyType, r.GetByte()), null);
- });
- writeDelegates.Add((inf, w) =>
- {
- w.Put((byte)property.GetValue(inf, null));
- });
- }
+ serialzer = new EnumByteSerializer(property, propertyType);
else if (underlyingType == typeof(int))
- {
- readDelegates.Add((inf, r) =>
- {
- property.SetValue(inf, Enum.ToObject(propertyType, r.GetInt()), null);
- });
- writeDelegates.Add((inf, w) =>
- {
- w.Put((int)property.GetValue(inf, null));
- });
- }
+ serialzer = new EnumIntSerializer(property, propertyType);
else
- {
throw new InvalidTypeException("Not supported enum underlying type: " + underlyingType.Name);
- }
- }
- else if (propertyType == typeof(string))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- if (_maxStringLength <= 0)
- {
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetString()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else
- {
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetString(_maxStringLength)));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf), _maxStringLength));
- }
}
- else if (propertyType == typeof(bool))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetBool()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(byte))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetByte()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(sbyte))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetSByte()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(short))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetShort()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(ushort))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetUShort()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(int))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetInt()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(uint))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetUInt()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(long))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetLong()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(ulong))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetULong()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(float))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetFloat()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(double))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetDouble()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(char))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetChar()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- else if (propertyType == typeof(IPEndPoint))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetNetEndPoint()));
- writeDelegates.Add((inf, w) => w.Put(getDelegate(inf)));
- }
- // Array types
- else if (propertyType == typeof(string[]))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- if (_maxStringLength <= 0)
- {
- readDelegates.Add((inf, r) => setDelegate( inf, r.GetStringArray()));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate( inf)));
- }
- else
- {
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetStringArray(_maxStringLength)));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate(inf), _maxStringLength));
- }
- }
- else if (propertyType == typeof(bool[]))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetBoolArray()));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate(inf)));
- }
- else if (propertyType == typeof(byte[]))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetBytesWithLength()));
- writeDelegates.Add((inf, w) => w.PutBytesWithLength(getDelegate(inf)));
- }
- else if (propertyType == typeof(short[]))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetShortArray()));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate(inf)));
- }
- else if (propertyType == typeof(ushort[]))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetUShortArray()));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate(inf)));
- }
- else if (propertyType == typeof(int[]))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetIntArray()));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate(inf)));
- }
- else if (propertyType == typeof(uint[]))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetUIntArray()));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate(inf)));
- }
- else if (propertyType == typeof(long[]))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetLongArray()));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate(inf)));
- }
- else if (propertyType == typeof(ulong[]))
- {
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetULongArray()));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate(inf)));
- }
- else if (propertyType == typeof(float[]))
+ else if (elementType == typeof(string))
+ serialzer = new StringSerializer(_maxStringLength);
+ else if (elementType == typeof(bool))
+ serialzer = new BoolSerializer();
+ else if (elementType == typeof(byte))
+ serialzer = new ByteSerializer();
+ else if (elementType == typeof(sbyte))
+ serialzer = new SByteSerializer();
+ else if (elementType == typeof(short))
+ serialzer = new ShortSerializer();
+ else if (elementType == typeof(ushort))
+ serialzer = new UShortSerializer();
+ else if (elementType == typeof(int))
+ serialzer = new IntSerializer();
+ else if (elementType == typeof(uint))
+ serialzer = new UIntSerializer();
+ else if (elementType == typeof(long))
+ serialzer = new LongSerializer();
+ else if (elementType == typeof(ulong))
+ serialzer = new ULongSerializer();
+ else if (elementType == typeof(float))
+ serialzer = new FloatSerializer();
+ else if (elementType == typeof(double))
+ serialzer = new DoubleSerializer();
+ else if (elementType == typeof(char))
+ serialzer = new CharSerializer();
+ else if (elementType == typeof(IPEndPoint))
+ serialzer = new IPEndPointSerializer();
+ else
{
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetFloatArray()));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate(inf)));
+ CustomType customType;
+ _registeredTypes.TryGetValue(elementType, out customType);
+ if (customType != null)
+ serialzer = customType.Get();
}
- else if (propertyType == typeof(double[]))
+
+ if (serialzer != null)
{
- var setDelegate = ExtractSetDelegate(setMethod);
- var getDelegate = ExtractGetDelegate(getMethod);
- readDelegates.Add((inf, r) => setDelegate(inf, r.GetDoubleArray()));
- writeDelegates.Add((inf, w) => w.PutArray(getDelegate(inf)));
+ serialzer.Init(getMethod, setMethod, propertyType.IsArray);
+ serializers.Add(serialzer);
}
else
{
- NestedType registeredNestedType;
- bool array = false;
-
- if (propertyType.IsArray)
- {
- array = true;
- propertyType = propertyType.GetElementType();
- }
-
- if (_registeredNestedTypes.TryGetValue(propertyType, out registeredNestedType))
- {
- if (array) //Array type serialize/deserialize
- {
- readDelegates.Add((inf, r) => property.SetValue(inf, registeredNestedType.ArrayReader(r), null));
- writeDelegates.Add((inf, w) => registeredNestedType.ArrayWriter(w, property.GetValue(inf, null)));
- }
- else //Simple
- {
- readDelegates.Add((inf, r) => property.SetValue(inf, registeredNestedType.ReadDelegate(r), null));
- writeDelegates.Add((inf, w) => registeredNestedType.WriteDelegate(w, property.GetValue(inf, null)));
- }
- }
- else
- {
- throw new InvalidTypeException("Unknown property type: " + propertyType.FullName);
- }
+ throw new InvalidTypeException("Unknown property type: " + propertyType.FullName);
}
}
- ClassInfo.Instance = new ClassInfo(readDelegates, writeDelegates);
+ ClassInfo.Instance = new ClassInfo(serializers);
return ClassInfo.Instance;
}
@@ -595,6 +591,8 @@ public void Register()
/// byte array with serialized data
public byte[] Serialize(T obj) where T : class, new()
{
+ if (_writer == null)
+ _writer = new NetDataWriter();
_writer.Reset();
Serialize(_writer, obj);
return _writer.CopyData();
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NtpPacket.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NtpPacket.cs
index 52afdd5..3227094 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NtpPacket.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NtpPacket.cs
@@ -293,9 +293,7 @@ internal NtpPacket(byte[] bytes)
///
public static NtpPacket FromServerResponse(byte[] bytes, DateTime destinationTimestamp)
{
- var packet = new NtpPacket(bytes);
- packet.DestinationTimestamp = destinationTimestamp;
- return packet;
+ return new NtpPacket(bytes) { DestinationTimestamp = destinationTimestamp };
}
internal void ValidateRequest()
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NtpRequest.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NtpRequest.cs
index 59cef85..78be782 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NtpRequest.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/Dependencies/LiteNetLib/Utils/NtpRequest.cs
@@ -107,7 +107,7 @@ public void Send()
///
public void Close()
{
- _socket.Close();
+ _socket.Close(false);
}
///
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/LiteNetLib4MirrorNetworkManager.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/LiteNetLib4MirrorNetworkManager.cs
index 08607ce..fb4a007 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/LiteNetLib4MirrorNetworkManager.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/LiteNetLib4MirrorNetworkManager.cs
@@ -16,7 +16,6 @@ public override void Awake()
GetComponent().InitializeTransport();
base.Awake();
singleton = this;
- NetworkManager.singleton = this;
}
///
@@ -87,7 +86,7 @@ public void StartHost(string serverIPv4BindAddress, string serverIPv6BindAddress
#if DISABLE_IPV6
public bool StartServer(string serverIPv4BindAddress, ushort port, ushort maxPlayers)
#else
- public bool StartServer(string serverIPv4BindAddress, string serverIPv6BindAddress, ushort port, ushort maxPlayers)
+ public void StartServer(string serverIPv4BindAddress, string serverIPv6BindAddress, ushort port, ushort maxPlayers)
#endif
{
networkAddress = serverIPv4BindAddress;
@@ -99,7 +98,7 @@ public bool StartServer(string serverIPv4BindAddress, string serverIPv6BindAddre
#endif
LiteNetLib4MirrorTransport.Singleton.port = port;
LiteNetLib4MirrorTransport.Singleton.maxConnections = maxPlayers;
- return StartServer();
+ StartServer();
}
///
@@ -126,7 +125,7 @@ public void StartHost(ushort port, ushort maxPlayers)
///
/// Port
/// Connection limit
- public bool StartServer(ushort port, ushort maxPlayers)
+ public void StartServer(ushort port, ushort maxPlayers)
{
networkAddress = "127.0.0.1";
maxConnections = maxPlayers;
@@ -136,7 +135,7 @@ public bool StartServer(ushort port, ushort maxPlayers)
#endif
LiteNetLib4MirrorTransport.Singleton.port = port;
LiteNetLib4MirrorTransport.Singleton.maxConnections = maxPlayers;
- return StartServer();
+ StartServer();
}
public void DisconnectConnection(NetworkConnection conn, string message = null)
diff --git a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/LiteNetLib4MirrorTransport.cs b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/LiteNetLib4MirrorTransport.cs
index 393b131..7703a33 100644
--- a/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/LiteNetLib4MirrorTransport.cs
+++ b/LiteNetLib4Mirror/Assets/Mirror/Runtime/Transport/LiteNetLib4Mirror/LiteNetLib4MirrorTransport.cs
@@ -124,7 +124,7 @@ protected internal virtual void GetConnectData(NetDataWriter writer)
protected internal virtual void ProcessConnectionRequest(ConnectionRequest request)
{
- if (LiteNetLib4MirrorCore.Host.PeersCount >= maxConnections)
+ if (LiteNetLib4MirrorCore.Host.ConnectedPeersCount >= maxConnections)
{
request.Reject();
}
@@ -212,6 +212,16 @@ public override void ClientDisconnect()
}
}
+ public override Uri ServerUri()
+ {
+ UriBuilder builder = new UriBuilder
+ {
+ Host = ipv6Enabled ? serverIPv6BindAddress : serverIPv4BindAddress,
+ Port = port
+ };
+ return builder.Uri;
+ }
+
public override bool ServerActive()
{
return LiteNetLib4MirrorServer.IsActive();
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/BasicAuthenticator.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/BasicAuthenticator.cs
index 454cbff..1f0a4ca 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/BasicAuthenticator.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/BasicAuthenticator.cs
@@ -1,11 +1,13 @@
-using UnityEngine;
using System.Collections;
+using UnityEngine;
namespace Mirror.Authenticators
{
[AddComponentMenu("Network/Authenticators/BasicAuthenticator")]
public class BasicAuthenticator : NetworkAuthenticator
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(BasicAuthenticator));
+
[Header("Custom Properties")]
// set these in the inspector
@@ -51,12 +53,12 @@ public override void OnClientAuthenticate(NetworkConnection conn)
authPassword = password
};
- NetworkClient.Send(authRequestMessage);
+ conn.Send(authRequestMessage);
}
public void OnAuthRequestMessage(NetworkConnection conn, AuthRequestMessage msg)
{
- Debug.LogFormat("Authentication Request: {0} {1}", msg.authUsername, msg.authPassword);
+ if (logger.LogEnabled()) logger.LogFormat(LogType.Log, "Authentication Request: {0} {1}", msg.authUsername, msg.authPassword);
// check the credentials by calling your web server, database table, playfab api, or any method appropriate.
if (msg.authUsername == username && msg.authPassword == password)
@@ -68,10 +70,10 @@ public void OnAuthRequestMessage(NetworkConnection conn, AuthRequestMessage msg)
message = "Success"
};
- NetworkServer.SendToClient(conn.connectionId, authResponseMessage);
+ conn.Send(authResponseMessage);
// Invoke the event to complete a successful authentication
- base.OnServerAuthenticated.Invoke(conn);
+ OnServerAuthenticated.Invoke(conn);
}
else
{
@@ -82,28 +84,34 @@ public void OnAuthRequestMessage(NetworkConnection conn, AuthRequestMessage msg)
message = "Invalid Credentials"
};
- NetworkServer.SendToClient(conn.connectionId, authResponseMessage);
+ conn.Send(authResponseMessage);
// must set NetworkConnection isAuthenticated = false
conn.isAuthenticated = false;
// disconnect the client after 1 second so that response message gets delivered
- Invoke(nameof(conn.Disconnect), 1);
+ StartCoroutine(DelayedDisconnect(conn, 1));
}
}
+ public IEnumerator DelayedDisconnect(NetworkConnection conn, float waitTime)
+ {
+ yield return new WaitForSeconds(waitTime);
+ conn.Disconnect();
+ }
+
public void OnAuthResponseMessage(NetworkConnection conn, AuthResponseMessage msg)
{
if (msg.code == 100)
{
- Debug.LogFormat("Authentication Response: {0}", msg.message);
+ if (logger.LogEnabled()) logger.LogFormat(LogType.Log, "Authentication Response: {0}", msg.message);
// Invoke the event to complete a successful authentication
- base.OnClientAuthenticated.Invoke(conn);
+ OnClientAuthenticated.Invoke(conn);
}
else
{
- Debug.LogErrorFormat("Authentication Response: {0}", msg.message);
+ logger.LogFormat(LogType.Error, "Authentication Response: {0}", msg.message);
// Set this on the client for local reference
conn.isAuthenticated = false;
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/BasicAuthenticator.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/BasicAuthenticator.cs.meta
index 5984986..4765013 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/BasicAuthenticator.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/BasicAuthenticator.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/TimeoutAuthenticator.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/TimeoutAuthenticator.cs
new file mode 100644
index 0000000..4fa580b
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/TimeoutAuthenticator.cs
@@ -0,0 +1,64 @@
+using System.Collections;
+using UnityEngine;
+
+namespace Mirror.Authenticators
+{
+ ///
+ /// An authenticator that disconnects connections if they don't
+ /// authenticate within a specified time limit.
+ ///
+ [AddComponentMenu("Network/Authenticators/TimeoutAuthenticator")]
+ public class TimeoutAuthenticator : NetworkAuthenticator
+ {
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(TimeoutAuthenticator));
+
+ public NetworkAuthenticator authenticator;
+
+ [Range(0, 600), Tooltip("Timeout to auto-disconnect in seconds. Set to 0 for no timeout.")]
+ public float timeout = 60;
+
+ public void Awake()
+ {
+ authenticator.OnClientAuthenticated.AddListener(connection => OnClientAuthenticated.Invoke(connection));
+ authenticator.OnServerAuthenticated.AddListener(connection => OnServerAuthenticated.Invoke(connection));
+ }
+
+ public override void OnStartClient()
+ {
+ authenticator.OnStartClient();
+ }
+
+ public override void OnStartServer()
+ {
+ authenticator.OnStartServer();
+ }
+
+ public override void OnClientAuthenticate(NetworkConnection conn)
+ {
+ authenticator.OnClientAuthenticate(conn);
+ if (timeout > 0)
+ StartCoroutine(BeginAuthentication(conn));
+ }
+
+ public override void OnServerAuthenticate(NetworkConnection conn)
+ {
+ authenticator.OnServerAuthenticate(conn);
+ if (timeout > 0)
+ StartCoroutine(BeginAuthentication(conn));
+ }
+
+ IEnumerator BeginAuthentication(NetworkConnection conn)
+ {
+ if (logger.LogEnabled()) logger.Log($"Authentication countdown started {conn} {timeout}");
+
+ yield return new WaitForSecondsRealtime(timeout);
+
+ if (!conn.isAuthenticated)
+ {
+ if (logger.LogEnabled()) logger.Log($"Authentication Timeout {conn}");
+
+ conn.Disconnect();
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/TimeoutAuthenticator.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/TimeoutAuthenticator.cs.meta
new file mode 100644
index 0000000..b19ddec
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Authenticators/TimeoutAuthenticator.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 24d8269a07b8e4edfa374753a91c946e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud.meta
similarity index 77%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud.meta
index bf61013..3f4322b 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: b84b2a39b3027c747b21ad714a439214
+guid: 6c37be755e166194288aeeedef468dea
folderAsset: yes
DefaultImporter:
externalObjects: {}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ApiConnector.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ApiConnector.cs
new file mode 100644
index 0000000..fb6713f
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ApiConnector.cs
@@ -0,0 +1,61 @@
+using Mirror.Cloud.ListServerService;
+using UnityEngine;
+
+namespace Mirror.Cloud
+{
+ ///
+ /// Used to requests and responses from the mirror api
+ ///
+ public interface IApiConnector
+ {
+ ListServer ListServer { get; }
+ }
+
+ ///
+ /// Used to requests and responses from the mirror api
+ ///
+ [DisallowMultipleComponent]
+ [AddComponentMenu("Network/CloudServices/ApiConnector")]
+ [HelpURL("https://mirror-networking.com/docs/CloudServices/ApiConnector.html")]
+ public class ApiConnector : MonoBehaviour, IApiConnector, ICoroutineRunner
+ {
+ #region Inspector
+ [Header("Settings")]
+
+ [Tooltip("Base URL of api, including https")]
+ [SerializeField] string ApiAddress = "";
+
+ [Tooltip("Api key required to access api")]
+ [SerializeField] string ApiKey = "";
+
+ [Header("Events")]
+
+ [Tooltip("Triggered when server list updates")]
+ [SerializeField] ServerListEvent _onServerListUpdated = new ServerListEvent();
+ #endregion
+
+ IRequestCreator requestCreator;
+
+ public ListServer ListServer { get; private set; }
+
+ void Awake()
+ {
+ requestCreator = new RequestCreator(ApiAddress, ApiKey, this);
+
+ InitListServer();
+ }
+
+ void InitListServer()
+ {
+ IListServerServerApi serverApi = new ListServerServerApi(this, requestCreator);
+ IListServerClientApi clientApi = new ListServerClientApi(this, requestCreator, _onServerListUpdated);
+ ListServer = new ListServer(serverApi, clientApi);
+ }
+
+ public void OnDestroy()
+ {
+ ListServer.ServerApi.Shutdown();
+ ListServer.ClientApi.Shutdown();
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ApiConnector.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ApiConnector.cs.meta
new file mode 100644
index 0000000..9279c0c
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ApiConnector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8bdb99a29e179d14cb0acc43f175d9ad
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/AnimationControllers.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core.meta
similarity index 77%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/AnimationControllers.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core.meta
index c9cd79f..8c00059 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/AnimationControllers.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 4969918300bfa9a4a8c733975df74016
+guid: 3f34c32971e65984c93a15376ec11c65
folderAsset: yes
DefaultImporter:
externalObjects: {}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/BaseApi.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/BaseApi.cs
new file mode 100644
index 0000000..720f598
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/BaseApi.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Mirror.Cloud
+{
+ public interface IBaseApi
+ {
+ ///
+ /// Cleans up any data created by the instance
+ /// For Example: removing server from list
+ ///
+ void Shutdown();
+ }
+
+ public abstract class BaseApi
+ {
+ protected readonly ICoroutineRunner runner;
+ protected readonly IRequestCreator requestCreator;
+
+ protected BaseApi(ICoroutineRunner runner, IRequestCreator requestCreator)
+ {
+ this.runner = runner ?? throw new ArgumentNullException(nameof(runner));
+ this.requestCreator = requestCreator ?? throw new ArgumentNullException(nameof(requestCreator));
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/BaseApi.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/BaseApi.cs.meta
new file mode 100644
index 0000000..f66b84e
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/BaseApi.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 70f563b7a7210ae43bbcde5cb7721a94
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Events.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Events.cs
new file mode 100644
index 0000000..ffee4d3
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Events.cs
@@ -0,0 +1,12 @@
+using System;
+using Mirror.Cloud.ListServerService;
+using UnityEngine.Events;
+
+namespace Mirror.Cloud
+{
+ [Serializable]
+ public class ServerListEvent : UnityEvent { }
+
+ [Serializable]
+ public class MatchFoundEvent : UnityEvent { }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Events.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Events.cs.meta
new file mode 100644
index 0000000..150d85b
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Events.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c7c472a3ea1bc4348bd5a0b05bf7cc3b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Extensions.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Extensions.cs
new file mode 100644
index 0000000..fa7dfa7
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Extensions.cs
@@ -0,0 +1,12 @@
+using UnityEngine.Networking;
+
+namespace Mirror.Cloud
+{
+ public static class Extensions
+ {
+ public static bool IsOk(this UnityWebRequest webRequest)
+ {
+ return 200 <= webRequest.responseCode && webRequest.responseCode <= 299;
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Extensions.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Extensions.cs.meta
new file mode 100644
index 0000000..6bf6291
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Extensions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 97501e783fc67a4459b15d10e6c63563
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/ICoroutineRunner.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/ICoroutineRunner.cs
new file mode 100644
index 0000000..7fe3bbf
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/ICoroutineRunner.cs
@@ -0,0 +1,12 @@
+using System.Collections;
+using UnityEngine;
+
+namespace Mirror.Cloud
+{
+ public interface ICoroutineRunner : IUnityEqualCheck
+ {
+ Coroutine StartCoroutine(IEnumerator routine);
+ void StopCoroutine(IEnumerator routine);
+ void StopCoroutine(Coroutine routine);
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/ICoroutineRunner.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/ICoroutineRunner.cs.meta
new file mode 100644
index 0000000..f1149a9
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/ICoroutineRunner.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 43472c60a7c72e54eafe559290dd0fc6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IRequestCreator.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IRequestCreator.cs
new file mode 100644
index 0000000..2709707
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IRequestCreator.cs
@@ -0,0 +1,42 @@
+using System.Collections;
+using UnityEngine.Networking;
+
+namespace Mirror.Cloud
+{
+ public delegate void RequestSuccess(string responseBody);
+
+ public delegate void RequestFail(string responseBody);
+
+ ///
+ /// Objects that can be sent to the Api must have this interface
+ ///
+ public interface ICanBeJson { }
+
+ ///
+ /// Methods to create and send UnityWebRequest
+ ///
+ public interface IRequestCreator
+ {
+ UnityWebRequest Delete(string page);
+ UnityWebRequest Get(string page);
+ UnityWebRequest Patch(string page, T json) where T : struct, ICanBeJson;
+ UnityWebRequest Post(string page, T json) where T : struct, ICanBeJson;
+
+ ///
+ /// Sends Request to api and invokes callback when finished
+ /// Starts Coroutine of SendRequestEnumerator
+ ///
+ ///
+ ///
+ ///
+ void SendRequest(UnityWebRequest request, RequestSuccess onSuccess = null, RequestFail onFail = null);
+ ///
+ /// Sends Request to api and invokes callback when finished
+ ///
+ ///
+ ///
+ ///
+ ///
+ IEnumerator SendRequestEnumerator(UnityWebRequest request, RequestSuccess onSuccess = null, RequestFail onFail = null);
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IRequestCreator.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IRequestCreator.cs.meta
new file mode 100644
index 0000000..966c503
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IRequestCreator.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b80b95532a9d6e8418aa676a261e4f69
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IUnityEqualCheck.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IUnityEqualCheck.cs
new file mode 100644
index 0000000..be5e057
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IUnityEqualCheck.cs
@@ -0,0 +1,26 @@
+using UnityEngine;
+
+namespace Mirror.Cloud
+{
+ ///
+ /// Adds Extension to check if unity object is null.
+ /// Use these methods to stop MissingReferenceException
+ ///
+ public interface IUnityEqualCheck
+ {
+
+ }
+
+ public static class UnityEqualCheckExtension
+ {
+ public static bool IsNull(this IUnityEqualCheck obj)
+ {
+ return (obj as Object) == null;
+ }
+
+ public static bool IsNotNull(this IUnityEqualCheck obj)
+ {
+ return (obj as Object) != null;
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IUnityEqualCheck.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IUnityEqualCheck.cs.meta
new file mode 100644
index 0000000..7cb2a59
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/IUnityEqualCheck.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 05185b973ba389a4588fc8a99c75a4f6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/JsonStructs.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/JsonStructs.cs
new file mode 100644
index 0000000..7827abc
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/JsonStructs.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Mirror.Cloud
+{
+ [Serializable]
+ public struct CreatedIdJson : ICanBeJson
+ {
+ public string id;
+ }
+
+ [Serializable]
+ public struct ErrorJson : ICanBeJson
+ {
+ public string code;
+ public string message;
+
+ public int HtmlCode => int.Parse(code);
+ }
+
+ [Serializable]
+ public struct EmptyJson : ICanBeJson
+ {
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/JsonStructs.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/JsonStructs.cs.meta
new file mode 100644
index 0000000..2c04009
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/JsonStructs.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0688c0fdae5376e4ea74d5c3904eed17
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Logger.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Logger.cs
new file mode 100644
index 0000000..89daca9
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Logger.cs
@@ -0,0 +1,72 @@
+using System;
+using UnityEngine;
+using UnityEngine.Networking;
+
+namespace Mirror.Cloud
+{
+ public static class Logger
+ {
+ public static bool VerboseLogging = false;
+ static readonly ILogger logger = LogFactory.GetLogger("MirrorCloudServices");
+
+ public static void LogRequest(string page, string method, bool hasJson, string json)
+ {
+ if (hasJson)
+ {
+ logger.LogFormat(LogType.Log, "Request: {0} {1} {2}", method, page, json);
+ }
+ else
+ {
+ logger.LogFormat(LogType.Log, "Request: {0} {1}", method, page);
+ }
+ }
+
+ public static void LogResponse(UnityWebRequest statusRequest)
+ {
+ long code = statusRequest.responseCode;
+ LogType logType = statusRequest.IsOk()
+ ? LogType.Log
+ : LogType.Error;
+
+ string format = "Response: {0} {1} {2} {3}";
+ if (logger.IsLogTypeAllowed(logType))
+ {
+ // we split path like this to make sure api key doesn't leak
+ Uri uri = new Uri(statusRequest.url);
+ string path = string.Join("", uri.Segments);
+ string msg = string.Format(format, statusRequest.method, code, path, statusRequest.downloadHandler.text);
+ logger.Log(logType, msg);
+ }
+
+ if (!string.IsNullOrEmpty(statusRequest.error))
+ {
+ string msg = string.Format("WEB REQUEST ERROR: {0}", statusRequest.error);
+ logger.Log(LogType.Error, msg);
+ }
+ }
+
+ internal static void Log(string msg)
+ {
+ if (logger.LogEnabled())
+ logger.Log(msg);
+ }
+
+ internal static void LogWarning(string msg)
+ {
+ if (logger.WarnEnabled())
+ logger.LogWarning(msg);
+ }
+
+ internal static void LogError(string msg)
+ {
+ if (logger.ErrorEnabled())
+ logger.LogError(msg);
+ }
+
+ internal static void Verbose(string msg)
+ {
+ if (VerboseLogging && logger.LogEnabled())
+ logger.Log(msg);
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Logger.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Logger.cs.meta
new file mode 100644
index 0000000..5984ce3
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/Logger.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 457ba2df6cb6e1542996c17c715ee81b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/RequestCreator.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/RequestCreator.cs
new file mode 100644
index 0000000..7195c0e
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/RequestCreator.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections;
+using System.Text;
+using UnityEngine;
+using UnityEngine.Networking;
+
+namespace Mirror.Cloud
+{
+ ///
+ /// Methods to create and send UnityWebRequest
+ ///
+ public class RequestCreator : IRequestCreator
+ {
+ const string GET = "GET";
+ const string POST = "POST";
+ const string PATCH = "PATCH";
+ const string DELETE = "DELETE";
+
+ public readonly string baseAddress;
+ public readonly string apiKey;
+ readonly ICoroutineRunner runner;
+
+ public RequestCreator(string baseAddress, string apiKey, ICoroutineRunner coroutineRunner)
+ {
+ if (string.IsNullOrEmpty(baseAddress))
+ {
+ throw new ArgumentNullException(nameof(baseAddress));
+ }
+
+ if (string.IsNullOrEmpty(apiKey))
+ {
+ throw new ArgumentNullException(nameof(apiKey));
+ }
+
+ this.baseAddress = baseAddress;
+ this.apiKey = apiKey;
+
+ runner = coroutineRunner ?? throw new ArgumentNullException(nameof(coroutineRunner));
+ }
+
+
+ Uri CreateUri(string page)
+ {
+ return new Uri(string.Format("{0}/{1}?key={2}", baseAddress, page, apiKey));
+ }
+
+ UnityWebRequest CreateWebRequest(string page, string method, string json = null)
+ {
+ bool hasJson = !string.IsNullOrEmpty(json);
+ Logger.LogRequest(page, method, hasJson, json);
+
+ UnityWebRequest request = new UnityWebRequest(CreateUri(page));
+ request.method = method;
+ if (hasJson)
+ {
+ request.SetRequestHeader("Content-Type", "application/json");
+ }
+
+ request.downloadHandler = new DownloadHandlerBuffer();
+
+ byte[] bodyRaw = hasJson
+ ? Encoding.UTF8.GetBytes(json)
+ : null;
+
+ request.uploadHandler = new UploadHandlerRaw(bodyRaw);
+
+ return request;
+ }
+
+
+
+ ///
+ /// Create Get Request to page
+ ///
+ ///
+ ///
+ public UnityWebRequest Get(string page)
+ {
+ return CreateWebRequest(page, GET);
+ }
+
+ ///
+ /// Creates Post Request to page with Json body
+ ///
+ ///
+ ///
+ ///
+ ///
+ public UnityWebRequest Post(string page, T json) where T : struct, ICanBeJson
+ {
+ string jsonString = JsonUtility.ToJson(json);
+ return CreateWebRequest(page, POST, jsonString);
+ }
+
+ ///
+ /// Creates Patch Request to page with Json body
+ ///
+ ///
+ ///
+ ///
+ ///
+ public UnityWebRequest Patch(string page, T json) where T : struct, ICanBeJson
+ {
+ string jsonString = JsonUtility.ToJson(json);
+ return CreateWebRequest(page, PATCH, jsonString);
+ }
+
+ ///
+ /// Create Delete Request to page
+ ///
+ ///
+ ///
+ public UnityWebRequest Delete(string page)
+ {
+ return CreateWebRequest(page, DELETE);
+ }
+
+
+ public void SendRequest(UnityWebRequest request, RequestSuccess onSuccess = null, RequestFail onFail = null)
+ {
+ runner.StartCoroutine(SendRequestEnumerator(request, onSuccess, onFail));
+ }
+
+ public IEnumerator SendRequestEnumerator(UnityWebRequest request, RequestSuccess onSuccess = null, RequestFail onFail = null)
+ {
+ using (UnityWebRequest webRequest = request)
+ {
+ yield return webRequest.SendWebRequest();
+ Logger.LogResponse(webRequest);
+
+ string text = webRequest.downloadHandler.text;
+ Logger.Verbose(text);
+ if (webRequest.IsOk())
+ {
+ onSuccess?.Invoke(text);
+ }
+ else
+ {
+ onFail?.Invoke(text);
+ }
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/RequestCreator.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/RequestCreator.cs.meta
new file mode 100644
index 0000000..eb139af
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Core/RequestCreator.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cfaa626443cc7c94eae138a2e3a04d7c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer.meta
similarity index 77%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer.meta
index af33e59..bc85c3d 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: e192f90e0acbb41f88dfe3dba300a5c9
+guid: c4c4be148a492b143a881cd08bf7e320
folderAsset: yes
DefaultImporter:
externalObjects: {}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServer.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServer.cs
new file mode 100644
index 0000000..8b4af80
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServer.cs
@@ -0,0 +1,66 @@
+using System;
+using UnityEngine.Events;
+
+namespace Mirror.Cloud.ListServerService
+{
+ public sealed class ListServer
+ {
+ public readonly IListServerServerApi ServerApi;
+ public readonly IListServerClientApi ClientApi;
+
+ public ListServer(IListServerServerApi serverApi, IListServerClientApi clientApi)
+ {
+ ServerApi = serverApi ?? throw new ArgumentNullException(nameof(serverApi));
+ ClientApi = clientApi ?? throw new ArgumentNullException(nameof(clientApi));
+ }
+ }
+
+ public interface IListServerServerApi : IBaseApi
+ {
+ ///
+ /// Has a server been added to the list with this connection
+ ///
+ bool ServerInList { get; }
+ ///
+ /// Add a server to the list
+ ///
+ ///
+ void AddServer(ServerJson server);
+ ///
+ /// Update the current server
+ ///
+ ///
+ void UpdateServer(int newPlayerCount);
+ ///
+ /// Update the current server
+ ///
+ ///
+ void UpdateServer(ServerJson server);
+ ///
+ /// Removes the current server
+ ///
+ void RemoveServer();
+ }
+
+ public interface IListServerClientApi : IBaseApi
+ {
+ ///
+ /// Called when the server list is updated
+ ///
+ event UnityAction onServerListUpdated;
+
+ ///
+ /// Get the server list once
+ ///
+ void GetServerList();
+ ///
+ /// Start getting the server list every interval
+ ///
+ ///
+ void StartGetServerListRepeat(int interval);
+ ///
+ /// Stop getting the server list
+ ///
+ void StopGetServerListRepeat();
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/ListServer.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServer.cs.meta
similarity index 83%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/ListServer.cs.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServer.cs.meta
index 35af6c4..519876d 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/ListServer.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServer.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 69f796b44735c414783d66f47b150c5f
+guid: 6f0311899162c5b49a3c11fa9bd9c133
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerBaseApi.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerBaseApi.cs
new file mode 100644
index 0000000..05d2e2e
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerBaseApi.cs
@@ -0,0 +1,9 @@
+namespace Mirror.Cloud.ListServerService
+{
+ public abstract class ListServerBaseApi : BaseApi
+ {
+ protected ListServerBaseApi(ICoroutineRunner runner, IRequestCreator requestCreator) : base(runner, requestCreator)
+ {
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerBaseApi.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerBaseApi.cs.meta
new file mode 100644
index 0000000..a9d32ea
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerBaseApi.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b6838f9df45594d48873518cbb75b329
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerClientApi.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerClientApi.cs
new file mode 100644
index 0000000..22867c1
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerClientApi.cs
@@ -0,0 +1,70 @@
+using System.Collections;
+using UnityEngine;
+using UnityEngine.Events;
+using UnityEngine.Networking;
+
+namespace Mirror.Cloud.ListServerService
+{
+ public sealed class ListServerClientApi : ListServerBaseApi, IListServerClientApi
+ {
+ readonly ServerListEvent _onServerListUpdated;
+
+ Coroutine getServerListRepeatCoroutine;
+
+ public event UnityAction onServerListUpdated
+ {
+ add => _onServerListUpdated.AddListener(value);
+ remove => _onServerListUpdated.RemoveListener(value);
+ }
+
+ public ListServerClientApi(ICoroutineRunner runner, IRequestCreator requestCreator, ServerListEvent onServerListUpdated) : base(runner, requestCreator)
+ {
+ _onServerListUpdated = onServerListUpdated;
+ }
+
+ public void Shutdown()
+ {
+ StopGetServerListRepeat();
+ }
+
+ public void GetServerList()
+ {
+ runner.StartCoroutine(getServerList());
+ }
+
+ public void StartGetServerListRepeat(int interval)
+ {
+ getServerListRepeatCoroutine = runner.StartCoroutine(GetServerListRepeat(interval));
+ }
+
+ public void StopGetServerListRepeat()
+ {
+ // if runner is null it has been destroyed and will alraedy be null
+ if (runner.IsNotNull() && getServerListRepeatCoroutine != null)
+ {
+ runner.StopCoroutine(getServerListRepeatCoroutine);
+ }
+ }
+
+ IEnumerator GetServerListRepeat(int interval)
+ {
+ while (true)
+ {
+ yield return getServerList();
+
+ yield return new WaitForSeconds(interval);
+ }
+ }
+ IEnumerator getServerList()
+ {
+ UnityWebRequest request = requestCreator.Get("servers");
+ yield return requestCreator.SendRequestEnumerator(request, onSuccess);
+
+ void onSuccess(string responseBody)
+ {
+ ServerCollectionJson serverlist = JsonUtility.FromJson(responseBody);
+ _onServerListUpdated?.Invoke(serverlist);
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerClientApi.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerClientApi.cs.meta
new file mode 100644
index 0000000..306bf7c
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerClientApi.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d49649fb32cb96b46b10f013b38a4b50
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerJson.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerJson.cs
new file mode 100644
index 0000000..2591331
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerJson.cs
@@ -0,0 +1,207 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Mirror.Cloud.ListServerService
+{
+ [Serializable]
+ public struct ServerCollectionJson : ICanBeJson
+ {
+ public ServerJson[] servers;
+ }
+
+ [Serializable]
+ public struct ServerJson : ICanBeJson
+ {
+ public string protocol;
+ public int port;
+ public int playerCount;
+ public int maxPlayerCount;
+
+ ///
+ /// optional
+ ///
+ public string displayName;
+
+ ///
+ /// Uri string of the ip and port of the server.
+ /// The ip is calculated by the request to the API
+ /// This is returns from the api, any incoming address fields will be ignored
+ ///
+ public string address;
+
+ ///
+ /// Can be used to set custom uri
+ /// optional
+ ///
+ public string customAddress;
+
+ ///
+ /// Array of custom data, use SetCustomData to set values
+ /// optional
+ ///
+ public KeyValue[] customData;
+
+ ///
+ /// Uri from address field
+ ///
+ ///
+ public Uri GetServerUri() => new Uri(address);
+
+ ///
+ /// Uri from customAddress field
+ ///
+ ///
+ public Uri GetCustomUri() => new Uri(customAddress);
+
+ ///
+ /// Updates the customData array
+ ///
+ ///
+ public void SetCustomData(Dictionary data)
+ {
+ if (data == null)
+ {
+ customData = null;
+ }
+ else
+ {
+ customData = data.ToKeyValueArray();
+ CustomDataHelper.ValidateCustomData(customData);
+ }
+ }
+
+ public bool Validate()
+ {
+ CustomDataHelper.ValidateCustomData(customData);
+
+ if (string.IsNullOrEmpty(protocol))
+ {
+ Logger.LogError("ServerJson should not have empty protocol");
+ return false;
+ }
+
+ if (port == 0)
+ {
+ Logger.LogError("ServerJson should not have port equal 0");
+ return false;
+ }
+
+ if (maxPlayerCount == 0)
+ {
+ Logger.LogError("ServerJson should not have maxPlayerCount equal 0");
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ [Serializable]
+ public struct PartialServerJson : ICanBeJson
+ {
+ ///
+ /// optional
+ ///
+ public int playerCount;
+
+ ///
+ /// optional
+ ///
+ public int maxPlayerCount;
+
+ ///
+ /// optional
+ ///
+ public string displayName;
+
+ ///
+ /// Array of custom data, use SetCustomData to set values
+ /// optional
+ ///
+ public KeyValue[] customData;
+
+
+ public void SetCustomData(Dictionary data)
+ {
+ if (data == null)
+ {
+ customData = null;
+ }
+ else
+ {
+ customData = data.ToKeyValueArray();
+ CustomDataHelper.ValidateCustomData(customData);
+ }
+ }
+
+ public void Validate()
+ {
+ CustomDataHelper.ValidateCustomData(customData);
+ }
+ }
+
+ public static class CustomDataHelper
+ {
+ const int MaxCustomData = 16;
+
+ public static Dictionary ToDictionary(this KeyValue[] keyValues)
+ {
+ return keyValues.ToDictionary(x => x.key, x => x.value);
+ }
+ public static KeyValue[] ToKeyValueArray(this Dictionary dictionary)
+ {
+ return dictionary.Select(kvp => new KeyValue(kvp.Key, kvp.Value)).ToArray();
+ }
+
+ public static void ValidateCustomData(KeyValue[] customData)
+ {
+ if (customData == null)
+ {
+ return;
+ }
+
+ if (customData.Length > MaxCustomData)
+ {
+ Logger.LogError($"There can only be {MaxCustomData} custom data but there was {customData.Length} values given");
+ Array.Resize(ref customData, MaxCustomData);
+ }
+
+ foreach (KeyValue item in customData)
+ {
+ item.Validate();
+ }
+ }
+ }
+
+ [Serializable]
+ public struct KeyValue
+ {
+ const int MaxKeySize = 32;
+ const int MaxValueSize = 256;
+
+ public string key;
+ public string value;
+
+ public KeyValue(string key, string value)
+ {
+ this.key = key;
+ this.value = value;
+ }
+
+ public void Validate()
+ {
+ if (key.Length > MaxKeySize)
+ {
+ Logger.LogError($"Custom Data must have key with length less than {MaxKeySize}");
+ key = key.Substring(0, MaxKeySize);
+ }
+
+ if (value.Length > MaxValueSize)
+ {
+ Logger.LogError($"Custom Data must have value with length less than {MaxValueSize}");
+ value = value.Substring(0, MaxValueSize);
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerJson.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerJson.cs.meta
new file mode 100644
index 0000000..7e206f1
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerJson.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a963606335eae0f47abe7ecb5fd028ea
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerServerApi.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerServerApi.cs
new file mode 100644
index 0000000..661a8b8
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerServerApi.cs
@@ -0,0 +1,219 @@
+using System.Collections;
+using UnityEngine;
+using UnityEngine.Networking;
+
+namespace Mirror.Cloud.ListServerService
+{
+ public sealed class ListServerServerApi : ListServerBaseApi, IListServerServerApi
+ {
+ const int PingInterval = 20;
+ const int MaxPingFails = 15;
+
+ ServerJson currentServer;
+ string serverId;
+
+ Coroutine _pingCoroutine;
+ ///
+ /// If the server has already been added
+ ///
+ bool added;
+ ///
+ /// if a request is currently sending
+ ///
+ bool sending;
+ ///
+ /// If an update request was recently sent
+ ///
+ bool skipNextPing;
+ ///
+ /// How many failed pings in a row
+ ///
+ int pingFails = 0;
+
+ public bool ServerInList => added;
+
+ public ListServerServerApi(ICoroutineRunner runner, IRequestCreator requestCreator) : base(runner, requestCreator)
+ {
+ }
+
+ public void Shutdown()
+ {
+ stopPingCoroutine();
+ if (added)
+ {
+ removeServerWithoutCoroutine();
+ }
+ added = false;
+ }
+
+ public void AddServer(ServerJson server)
+ {
+ if (added) { Logger.LogWarning("AddServer called when server was already adding or added"); return; }
+ bool valid = server.Validate();
+ if (!valid) { return; }
+
+ runner.StartCoroutine(addServer(server));
+ }
+
+ public void UpdateServer(int newPlayerCount)
+ {
+ if (!added) { Logger.LogWarning("UpdateServer called when before server was added"); return; }
+
+ currentServer.playerCount = newPlayerCount;
+ UpdateServer(currentServer);
+ }
+
+ public void UpdateServer(ServerJson server)
+ {
+ // TODO, use PartialServerJson as Arg Instead
+ if (!added) { Logger.LogWarning("UpdateServer called when before server was added"); return; }
+
+ PartialServerJson partialServer = new PartialServerJson
+ {
+ displayName = server.displayName,
+ playerCount = server.playerCount,
+ maxPlayerCount = server.maxPlayerCount,
+ customData = server.customData,
+ };
+ partialServer.Validate();
+
+ runner.StartCoroutine(updateServer(partialServer));
+ }
+
+ public void RemoveServer()
+ {
+ if (!added) { return; }
+
+ if (string.IsNullOrEmpty(serverId))
+ {
+ Debug.LogWarning("Can not remove server because serverId was empty");
+ return;
+ }
+
+ stopPingCoroutine();
+ runner.StartCoroutine(removeServer());
+ }
+
+ void stopPingCoroutine()
+ {
+ if (_pingCoroutine != null)
+ {
+ runner.StopCoroutine(_pingCoroutine);
+ _pingCoroutine = null;
+ }
+ }
+
+ IEnumerator addServer(ServerJson server)
+ {
+ added = true;
+ sending = true;
+ currentServer = server;
+
+ UnityWebRequest request = requestCreator.Post("servers", currentServer);
+ yield return requestCreator.SendRequestEnumerator(request, onSuccess, onFail);
+ sending = false;
+
+ void onSuccess(string responseBody)
+ {
+ CreatedIdJson created = JsonUtility.FromJson(responseBody);
+ serverId = created.id;
+
+ // Start ping to keep server alive
+ _pingCoroutine = runner.StartCoroutine(ping());
+ }
+ void onFail(string responseBody)
+ {
+ added = false;
+ }
+ }
+
+ IEnumerator updateServer(PartialServerJson server)
+ {
+ // wait to not be sending
+ while (sending)
+ {
+ yield return new WaitForSeconds(1);
+ }
+
+ // We need to check added incase Update is called soon after Add, and add failed
+ if (!added) { Logger.LogWarning("UpdateServer called when before server was added"); yield break; }
+
+ sending = true;
+ UnityWebRequest request = requestCreator.Patch("servers/" + serverId, server);
+ yield return requestCreator.SendRequestEnumerator(request, onSuccess);
+ sending = false;
+
+ void onSuccess(string responseBody)
+ {
+ skipNextPing = true;
+
+ if (_pingCoroutine == null)
+ {
+ _pingCoroutine = runner.StartCoroutine(ping());
+ }
+ }
+ }
+
+ ///
+ /// Keeps server alive in database
+ ///
+ ///
+ IEnumerator ping()
+ {
+ while (pingFails <= MaxPingFails)
+ {
+ yield return new WaitForSeconds(PingInterval);
+ if (skipNextPing)
+ {
+ skipNextPing = false;
+ continue;
+ }
+
+ sending = true;
+ UnityWebRequest request = requestCreator.Patch("servers/" + serverId, new EmptyJson());
+ yield return requestCreator.SendRequestEnumerator(request, onSuccess, onFail);
+ sending = false;
+ }
+
+ Logger.LogWarning("Max ping fails reached, stoping to ping server");
+ _pingCoroutine = null;
+
+
+ void onSuccess(string responseBody)
+ {
+ pingFails = 0;
+ }
+ void onFail(string responseBody)
+ {
+ pingFails++;
+ }
+ }
+
+ IEnumerator removeServer()
+ {
+ sending = true;
+ UnityWebRequest request = requestCreator.Delete("servers/" + serverId);
+ yield return requestCreator.SendRequestEnumerator(request);
+ sending = false;
+
+ added = false;
+ }
+
+ void removeServerWithoutCoroutine()
+ {
+ if (string.IsNullOrEmpty(serverId))
+ {
+ Debug.LogWarning("Can not remove server becuase serverId was empty");
+ return;
+ }
+
+ UnityWebRequest request = requestCreator.Delete("servers/" + serverId);
+ UnityWebRequestAsyncOperation operation = request.SendWebRequest();
+
+ operation.completed += (op) =>
+ {
+ Logger.LogResponse(request);
+ };
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerServerApi.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerServerApi.cs.meta
new file mode 100644
index 0000000..82e23fd
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/ListServer/ListServerServerApi.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 675f0d0fd4e82b04290c4d30c8d78ede
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Mirror.Examples.asmdef b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Mirror.Cloud.asmdef
similarity index 78%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Mirror.Examples.asmdef
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Mirror.Cloud.asmdef
index c4f942e..dbea971 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Mirror.Examples.asmdef
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Mirror.Cloud.asmdef
@@ -1,8 +1,7 @@
{
- "name": "Mirror.Examples",
+ "name": "Mirror.Cloud",
"references": [
- "Mirror",
- "Mirror.Components"
+ "Mirror"
],
"optionalUnityReferences": [],
"includePlatforms": [],
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Mirror.Examples.asmdef.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Mirror.Cloud.asmdef.meta
similarity index 76%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Mirror.Examples.asmdef.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Mirror.Cloud.asmdef.meta
index 2b545b5..bd17c2b 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Mirror.Examples.asmdef.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/Mirror.Cloud.asmdef.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: fecf25954bb196642ab50657689761d6
+guid: c21ba7b8c3183cb47b7fe3b3799d49c4
AssemblyDefinitionImporter:
externalObjects: {}
userData:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/README.md b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/README.md
new file mode 100644
index 0000000..5e476a2
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/README.md
@@ -0,0 +1,86 @@
+# Mirror Cloud Services
+
+## Mirror List Server
+
+Example has API key that can be used for as a demo.
+
+To get an API key to use within your game you can subscribe on the [Mirror Networking Website](https://mirror-networking.com/list-server/)
+
+### Key features
+
+- The Cloud Service works via https so is secure and can be used from any platform.
+- It runs on Google Cloud so there is no worry about server down time.
+- It scales really well. Default quota is 1000 API requests per minute. If you have high demands, contact us and we can increase that limit.
+
+## List Server Examples
+
+An example for this can be found in Mirror/Examples/Cloud/
+
+*Note: you can not connect to your own public ip address, you will need at least people to test this*
+
+## How to use
+
+Add `ApiConnector` component to an object in your game, It is probably best to put this on the same object as your NetworkManager. Once it has been added set the `ApiAddress` and `ApiKey` fields.
+
+To use `ApiConnector` either directly reference it in an inspector field or get it when your script awakes
+```cs
+ApiConnector connector;
+
+void Awake()
+{
+ connector = FindObjectOfType();
+}
+```
+
+
+The Api calls are grouped into objects. `connector.ListServer.ServerApi` has the Server api calls like `AddServer`. `connector.ListServer.ClientApi` has the Client Api calls like `GetServerList`.
+
+### Server Api Example
+
+Example of how to add server
+```cs
+void AddServer(int playerCount)
+{
+ Transport transport = Transport.activeTransport;
+
+ Uri uri = transport.ServerUri();
+ int port = uri.Port;
+ string protocol = uri.Scheme;
+
+ connector.ListServer.ServerApi.AddServer(new ServerJson
+ {
+ displayName = "Fun game!!!",
+ protocol = protocol,
+ port = port,
+ maxPlayerCount = NetworkManager.singleton.maxConnections,
+ playerCount = playerCount
+ });
+}
+```
+
+### Client Api Example
+Example of how to list servers
+
+```cs
+ApiConnector connector;
+
+void Awake()
+{
+ connector = FindObjectOfType();
+ // add listener to event that will update UI when Server list is refreshed
+ connector.ListServer.ClientApi.onServerListUpdated += onServerListUpdated;
+
+ // add listen to button so that player can refresh server list
+ refreshButton.onClick.AddListener(RefreshButtonHandler);
+}
+
+public void RefreshButtonHandler()
+{
+ connector.ListServer.ClientApi.GetServerList();
+}
+
+void onServerListUpdated()
+{
+ // Update UI here
+}
+```
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/README.md.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/README.md.meta
similarity index 75%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/README.md.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/README.md.meta
index 470c34f..d669f54 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/README.md.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/README.md.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 0a023e0d7315ac74094703ab69348733
+guid: 04945d14ccbed964597a1ee00805c059
TextScriptImporter:
externalObjects: {}
userData:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/version.txt b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/version.txt
new file mode 100644
index 0000000..7b0bc8d
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/version.txt
@@ -0,0 +1 @@
+MirrorCloudServices v0.1.0
\ No newline at end of file
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/README.md.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/version.txt.meta
similarity index 75%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/README.md.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/version.txt.meta
index d4e1715..1e13fd5 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/README.md.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Cloud/version.txt.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 67177defd4d334a549e535f10506cc66
+guid: bf81e376b88e68e48a47531b8bfeb0f4
TextScriptImporter:
externalObjects: {}
userData:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols.meta
similarity index 77%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols.meta
index d6629fb..09c87c4 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 7ef7a74859259a546b73ed820e449ae8
+guid: 3261925ead5d21d44bb91a8a3f9fb18e
folderAsset: yes
DefaultImporter:
externalObjects: {}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Tests/Mirror.Tests.asmdef b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef
similarity index 58%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Tests/Mirror.Tests.asmdef
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef
index 1463222..af25622 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Tests/Mirror.Tests.asmdef
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef
@@ -1,12 +1,7 @@
{
- "name": "Mirror.Tests",
- "references": [
- "Mirror",
- "Mirror.Weaver"
- ],
- "optionalUnityReferences": [
- "TestAssemblies"
- ],
+ "name": "Mirror.CompilerSymbols",
+ "references": [],
+ "optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Tests/Mirror.Tests.asmdef.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef.meta
similarity index 76%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Tests/Mirror.Tests.asmdef.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef.meta
index 4f23023..8b23823 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Tests/Mirror.Tests.asmdef.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 8b489029f75e64a7bbf6918bf1a49e39
+guid: 325984b52e4128546bc7558552f8b1d2
AssemblyDefinitionImporter:
externalObjects: {}
userData:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/PreprocessorDefine.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/PreprocessorDefine.cs
new file mode 100644
index 0000000..0c578ce
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/PreprocessorDefine.cs
@@ -0,0 +1,45 @@
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace Mirror
+{
+ static class PreprocessorDefine
+ {
+ ///
+ /// Add define symbols as soon as Unity gets done compiling.
+ ///
+ [InitializeOnLoadMethod]
+ public static void AddDefineSymbols()
+ {
+ string currentDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
+ HashSet defines = new HashSet(currentDefines.Split(';'))
+ {
+ "MIRROR",
+ "MIRROR_1726_OR_NEWER",
+ "MIRROR_3_0_OR_NEWER",
+ "MIRROR_3_12_OR_NEWER",
+ "MIRROR_4_0_OR_NEWER",
+ "MIRROR_5_0_OR_NEWER",
+ "MIRROR_6_0_OR_NEWER",
+ "MIRROR_7_0_OR_NEWER",
+ "MIRROR_8_0_OR_NEWER",
+ "MIRROR_9_0_OR_NEWER",
+ "MIRROR_10_0_OR_NEWER",
+ "MIRROR_11_0_OR_NEWER",
+ "MIRROR_12_0_OR_NEWER",
+ "MIRROR_13_0_OR_NEWER",
+ "MIRROR_14_0_OR_NEWER",
+ "MIRROR_15_0_OR_NEWER",
+ "MIRROR_16_0_OR_NEWER"
+ };
+
+ // only touch PlayerSettings if we actually modified it.
+ // otherwise it shows up as changed in git each time.
+ string newDefines = string.Join(";", defines);
+ if (newDefines != currentDefines)
+ {
+ PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, newDefines);
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/PreprocessorDefine.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/PreprocessorDefine.cs.meta
similarity index 100%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/PreprocessorDefine.cs.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/CompilerSymbols/PreprocessorDefine.cs.meta
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery.meta
new file mode 100644
index 0000000..d5bb0cb
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: b5dcf9618f5e14a4eb60bff5480284a6
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscovery.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscovery.cs
new file mode 100644
index 0000000..dd64a34
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscovery.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Net;
+using UnityEngine;
+using UnityEngine.Events;
+
+namespace Mirror.Discovery
+{
+ [Serializable]
+ public class ServerFoundUnityEvent : UnityEvent { };
+
+ [DisallowMultipleComponent]
+ [AddComponentMenu("Network/NetworkDiscovery")]
+ public class NetworkDiscovery : NetworkDiscoveryBase
+ {
+ #region Server
+
+ public long ServerId { get; private set; }
+
+ [Tooltip("Transport to be advertised during discovery")]
+ public Transport transport;
+
+ [Tooltip("Invoked when a server is found")]
+ public ServerFoundUnityEvent OnServerFound;
+
+ public override void Start()
+ {
+ ServerId = RandomLong();
+
+ // active transport gets initialized in awake
+ // so make sure we set it here in Start() (after awakes)
+ // Or just let the user assign it in the inspector
+ if (transport == null)
+ transport = Transport.activeTransport;
+
+ base.Start();
+ }
+
+ ///
+ /// Process the request from a client
+ ///
+ ///
+ /// Override if you wish to provide more information to the clients
+ /// such as the name of the host player
+ ///
+ /// Request comming from client
+ /// Address of the client that sent the request
+ /// The message to be sent back to the client or null
+ protected override ServerResponse ProcessRequest(ServerRequest request, IPEndPoint endpoint)
+ {
+ // In this case we don't do anything with the request
+ // but other discovery implementations might want to use the data
+ // in there, This way the client can ask for
+ // specific game mode or something
+
+ try
+ {
+ // this is an example reply message, return your own
+ // to include whatever is relevant for your game
+ return new ServerResponse
+ {
+ serverId = ServerId,
+ uri = transport.ServerUri()
+ };
+ }
+ catch (NotImplementedException)
+ {
+ Debug.LogError($"Transport {transport} does not support network discovery");
+ throw;
+ }
+ }
+
+ #endregion
+
+ #region Client
+
+ ///
+ /// Create a message that will be broadcasted on the network to discover servers
+ ///
+ ///
+ /// Override if you wish to include additional data in the discovery message
+ /// such as desired game mode, language, difficulty, etc...
+ /// An instance of ServerRequest with data to be broadcasted
+ protected override ServerRequest GetRequest() => new ServerRequest();
+
+ ///
+ /// Process the answer from a server
+ ///
+ ///
+ /// A client receives a reply from a server, this method processes the
+ /// reply and raises an event
+ ///
+ /// Response that came from the server
+ /// Address of the server that replied
+ protected override void ProcessResponse(ServerResponse response, IPEndPoint endpoint)
+ {
+ // we received a message from the remote endpoint
+ response.EndPoint = endpoint;
+
+ // although we got a supposedly valid url, we may not be able to resolve
+ // the provided host
+ // However we know the real ip address of the server because we just
+ // received a packet from it, so use that as host.
+ UriBuilder realUri = new UriBuilder(response.uri)
+ {
+ Host = response.EndPoint.Address.ToString()
+ };
+ response.uri = realUri.Uri;
+
+ OnServerFound.Invoke(response);
+ }
+
+ #endregion
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscovery.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscovery.cs.meta
new file mode 100644
index 0000000..c691a61
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscovery.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c761308e733c51245b2e8bb4201f46dc
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryBase.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryBase.cs
new file mode 100644
index 0000000..daf4137
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryBase.cs
@@ -0,0 +1,363 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading.Tasks;
+using UnityEngine;
+
+// Based on https://github.com/EnlightenedOne/MirrorNetworkDiscovery
+// forked from https://github.com/in0finite/MirrorNetworkDiscovery
+// Both are MIT Licensed
+
+namespace Mirror.Discovery
+{
+ ///
+ /// Base implementation for Network Discovery. Extend this component
+ /// to provide custom discovery with game specific data
+ /// NetworkDiscovery for a sample implementation
+ ///
+ [DisallowMultipleComponent]
+ [HelpURL("https://mirror-networking.com/docs/Components/NetworkDiscovery.html")]
+ public abstract class NetworkDiscoveryBase : MonoBehaviour
+ where Request : IMessageBase, new()
+ where Response : IMessageBase, new()
+ {
+ public static bool SupportedOnThisPlatform { get { return Application.platform != RuntimePlatform.WebGLPlayer; } }
+
+ // each game should have a random unique handshake, this way you can tell if this is the same game or not
+ [HideInInspector]
+ public long secretHandshake;
+
+ [SerializeField]
+ [Tooltip("The UDP port the server will listen for multi-cast messages")]
+ protected int serverBroadcastListenPort = 47777;
+
+ [SerializeField]
+ [Tooltip("Time in seconds between multi-cast messages")]
+ [Range(1, 60)]
+ float ActiveDiscoveryInterval = 3;
+
+ protected UdpClient serverUdpClient;
+ protected UdpClient clientUdpClient;
+
+#if UNITY_EDITOR
+ void OnValidate()
+ {
+ if (secretHandshake == 0)
+ {
+ secretHandshake = RandomLong();
+ UnityEditor.Undo.RecordObject(this, "Set secret handshake");
+ }
+ }
+#endif
+
+ public static long RandomLong()
+ {
+ int value1 = UnityEngine.Random.Range(int.MinValue, int.MaxValue);
+ int value2 = UnityEngine.Random.Range(int.MinValue, int.MaxValue);
+ return value1 + ((long)value2 << 32);
+ }
+
+ ///
+ /// virtual so that inheriting classes' Start() can call base.Start() too
+ ///
+ public virtual void Start()
+ {
+ // headless mode? then start advertising
+ if (NetworkManager.isHeadless)
+ {
+ AdvertiseServer();
+ }
+ }
+
+ // Ensure the ports are cleared no matter when Game/Unity UI exits
+ void OnApplicationQuit()
+ {
+ Shutdown();
+ }
+
+ void Shutdown()
+ {
+ if (serverUdpClient != null)
+ {
+ try
+ {
+ serverUdpClient.Close();
+ }
+ catch (Exception)
+ {
+ // it is just close, swallow the error
+ }
+
+ serverUdpClient = null;
+ }
+
+ if (clientUdpClient != null)
+ {
+ try
+ {
+ clientUdpClient.Close();
+ }
+ catch (Exception)
+ {
+ // it is just close, swallow the error
+ }
+
+ clientUdpClient = null;
+ }
+
+ CancelInvoke();
+ }
+
+ #region Server
+
+ ///
+ /// Advertise this server in the local network
+ ///
+ public void AdvertiseServer()
+ {
+ if (!SupportedOnThisPlatform)
+ throw new PlatformNotSupportedException("Network discovery not supported in this platform");
+
+ StopDiscovery();
+
+ // Setup port -- may throw exception
+ serverUdpClient = new UdpClient(serverBroadcastListenPort)
+ {
+ EnableBroadcast = true,
+ MulticastLoopback = false
+ };
+
+ // listen for client pings
+ _ = ServerListenAsync();
+ }
+
+ public async Task ServerListenAsync()
+ {
+ while (true)
+ {
+ try
+ {
+ await ReceiveRequestAsync(serverUdpClient);
+ }
+ catch (ObjectDisposedException)
+ {
+ // socket has been closed
+ break;
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ async Task ReceiveRequestAsync(UdpClient udpClient)
+ {
+ // only proceed if there is available data in network buffer, or otherwise Receive() will block
+ // average time for UdpClient.Available : 10 us
+
+ UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();
+
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(udpReceiveResult.Buffer))
+ {
+ long handshake = networkReader.ReadInt64();
+ if (handshake != secretHandshake)
+ {
+ // message is not for us
+ throw new ProtocolViolationException("Invalid handshake");
+ }
+
+ Request request = new Request();
+ request.Deserialize(networkReader);
+
+ ProcessClientRequest(request, udpReceiveResult.RemoteEndPoint);
+ }
+ }
+
+ ///
+ /// Reply to the client to inform it of this server
+ ///
+ ///
+ /// Override if you wish to ignore server requests based on
+ /// custom criteria such as language, full server game mode or difficulty
+ ///
+ /// Request comming from client
+ /// Address of the client that sent the request
+ protected virtual void ProcessClientRequest(Request request, IPEndPoint endpoint)
+ {
+ Response info = ProcessRequest(request, endpoint);
+
+ if (info == null)
+ return;
+
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
+ {
+ try
+ {
+ writer.WriteInt64(secretHandshake);
+
+ info.Serialize(writer);
+
+ ArraySegment data = writer.ToArraySegment();
+ // signature matches
+ // send response
+ serverUdpClient.Send(data.Array, data.Count, endpoint);
+ }
+ catch (Exception ex)
+ {
+ Debug.LogException(ex, this);
+ }
+ }
+ }
+
+ ///
+ /// Process the request from a client
+ ///
+ ///
+ /// Override if you wish to provide more information to the clients
+ /// such as the name of the host player
+ ///
+ /// Request comming from client
+ /// Address of the client that sent the request
+ /// The message to be sent back to the client or null
+ protected abstract Response ProcessRequest(Request request, IPEndPoint endpoint);
+
+ #endregion
+
+ #region Client
+
+ ///
+ /// Start Active Discovery
+ ///
+ public void StartDiscovery()
+ {
+ if (!SupportedOnThisPlatform)
+ throw new PlatformNotSupportedException("Network discovery not supported in this platform");
+
+ StopDiscovery();
+
+ try
+ {
+ // Setup port
+ clientUdpClient = new UdpClient(0)
+ {
+ EnableBroadcast = true,
+ MulticastLoopback = false
+ };
+ }
+ catch (Exception)
+ {
+ // Free the port if we took it
+ Shutdown();
+ throw;
+ }
+
+ _ = ClientListenAsync();
+
+ InvokeRepeating(nameof(BroadcastDiscoveryRequest), 0, ActiveDiscoveryInterval);
+ }
+
+ ///
+ /// Stop Active Discovery
+ ///
+ public void StopDiscovery()
+ {
+ Shutdown();
+ }
+
+ ///
+ /// Awaits for server response
+ ///
+ /// ClientListenAsync Task
+ public async Task ClientListenAsync()
+ {
+ while (true)
+ {
+ try
+ {
+ await ReceiveGameBroadcastAsync(clientUdpClient);
+ }
+ catch (ObjectDisposedException)
+ {
+ // socket was closed, no problem
+ return;
+ }
+ catch (Exception ex)
+ {
+ Debug.LogException(ex);
+ }
+ }
+ }
+
+ ///
+ /// Sends discovery request from client
+ ///
+ public void BroadcastDiscoveryRequest()
+ {
+ if (clientUdpClient == null)
+ return;
+
+ IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, serverBroadcastListenPort);
+
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
+ {
+ writer.WriteInt64(secretHandshake);
+
+ try
+ {
+ Request request = GetRequest();
+
+ request.Serialize(writer);
+
+ ArraySegment data = writer.ToArraySegment();
+
+ clientUdpClient.SendAsync(data.Array, data.Count, endPoint);
+ }
+ catch (Exception)
+ {
+ // It is ok if we can't broadcast to one of the addresses
+ }
+ }
+ }
+
+ ///
+ /// Create a message that will be broadcasted on the network to discover servers
+ ///
+ ///
+ /// Override if you wish to include additional data in the discovery message
+ /// such as desired game mode, language, difficulty, etc...
+ /// An instance of ServerRequest with data to be broadcasted
+ protected virtual Request GetRequest() => new Request();
+
+ async Task ReceiveGameBroadcastAsync(UdpClient udpClient)
+ {
+ // only proceed if there is available data in network buffer, or otherwise Receive() will block
+ // average time for UdpClient.Available : 10 us
+
+ UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();
+
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(udpReceiveResult.Buffer))
+ {
+ if (networkReader.ReadInt64() != secretHandshake)
+ return;
+
+ Response response = new Response();
+ response.Deserialize(networkReader);
+
+ ProcessResponse(response, udpReceiveResult.RemoteEndPoint);
+ }
+ }
+
+ ///
+ /// Process the answer from a server
+ ///
+ ///
+ /// A client receives a reply from a server, this method processes the
+ /// reply and raises an event
+ ///
+ /// Response that came from the server
+ /// Address of the server that replied
+ protected abstract void ProcessResponse(Response response, IPEndPoint endpoint);
+
+ #endregion
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryBase.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryBase.cs.meta
new file mode 100644
index 0000000..7dfbaf6
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryBase.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b9971d60ce61f4e39b07cd9e7e0c68fa
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs
new file mode 100644
index 0000000..cfb53d6
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs
@@ -0,0 +1,95 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Mirror.Discovery
+{
+ [DisallowMultipleComponent]
+ [AddComponentMenu("Network/NetworkDiscoveryHUD")]
+ [HelpURL("https://mirror-networking.com/docs/Components/NetworkDiscovery.html")]
+ [RequireComponent(typeof(NetworkDiscovery))]
+ public class NetworkDiscoveryHUD : MonoBehaviour
+ {
+ readonly Dictionary discoveredServers = new Dictionary();
+ Vector2 scrollViewPos = Vector2.zero;
+
+ public NetworkDiscovery networkDiscovery;
+
+#if UNITY_EDITOR
+ void OnValidate()
+ {
+ if (networkDiscovery == null)
+ {
+ networkDiscovery = GetComponent();
+ UnityEditor.Events.UnityEventTools.AddPersistentListener(networkDiscovery.OnServerFound, OnDiscoveredServer);
+ UnityEditor.Undo.RecordObjects(new Object[] { this, networkDiscovery }, "Set NetworkDiscovery");
+ }
+ }
+#endif
+
+ void OnGUI()
+ {
+ if (NetworkManager.singleton == null)
+ return;
+
+ if (NetworkServer.active || NetworkClient.active)
+ return;
+
+ if (!NetworkClient.isConnected && !NetworkServer.active && !NetworkClient.active)
+ DrawGUI();
+ }
+
+ void DrawGUI()
+ {
+ GUILayout.BeginHorizontal();
+
+ if (GUILayout.Button("Find Servers"))
+ {
+ discoveredServers.Clear();
+ networkDiscovery.StartDiscovery();
+ }
+
+ // LAN Host
+ if (GUILayout.Button("Start Host"))
+ {
+ discoveredServers.Clear();
+ NetworkManager.singleton.StartHost();
+ networkDiscovery.AdvertiseServer();
+ }
+
+ // Dedicated server
+ if (GUILayout.Button("Start Server"))
+ {
+ discoveredServers.Clear();
+ NetworkManager.singleton.StartServer();
+
+ networkDiscovery.AdvertiseServer();
+ }
+
+ GUILayout.EndHorizontal();
+
+ // show list of found server
+
+ GUILayout.Label($"Discovered Servers [{discoveredServers.Count}]:");
+
+ // servers
+ scrollViewPos = GUILayout.BeginScrollView(scrollViewPos);
+
+ foreach (ServerResponse info in discoveredServers.Values)
+ if (GUILayout.Button(info.EndPoint.Address.ToString()))
+ Connect(info);
+
+ GUILayout.EndScrollView();
+ }
+
+ void Connect(ServerResponse info)
+ {
+ NetworkManager.singleton.StartClient(info.uri);
+ }
+
+ public void OnDiscoveredServer(ServerResponse info)
+ {
+ // Note that you can check the versioning to decide if you can connect to the server or not using this method
+ discoveredServers[info.serverId] = info;
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs.meta
new file mode 100644
index 0000000..f93b275
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 88c37d3deca7a834d80cfd8d3cfcc510
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerRequest.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerRequest.cs
new file mode 100644
index 0000000..3ac59cf
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerRequest.cs
@@ -0,0 +1,4 @@
+namespace Mirror.Discovery
+{
+ public class ServerRequest : MessageBase { }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerRequest.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerRequest.cs.meta
new file mode 100644
index 0000000..84f3232
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerRequest.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ea7254bf7b9454da4adad881d94cd141
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerResponse.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerResponse.cs
new file mode 100644
index 0000000..34173e5
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerResponse.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Net;
+
+namespace Mirror.Discovery
+{
+ public class ServerResponse : MessageBase
+ {
+ // The server that sent this
+ // this is a property so that it is not serialized, but the
+ // client fills this up after we receive it
+ public IPEndPoint EndPoint { get; set; }
+
+ public Uri uri;
+
+ // Prevent duplicate server appearance when a connection can be made via LAN on multiple NICs
+ public long serverId;
+ }
+}
\ No newline at end of file
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerResponse.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerResponse.cs.meta
new file mode 100644
index 0000000..44f23ba
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Discovery/ServerResponse.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 36f97227fdf2d7a4e902db5bfc43039c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental.meta
new file mode 100644
index 0000000..57cce38
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: bfbf2a1f2b300c5489dcab219ef2846e
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkRigidbody.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkRigidbody.cs
new file mode 100644
index 0000000..fe85158
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkRigidbody.cs
@@ -0,0 +1,363 @@
+using UnityEngine;
+
+namespace Mirror.Experimental
+{
+ [AddComponentMenu("Network/Experimental/NetworkRigidbody")]
+ [HelpURL("https://mirror-networking.com/docs/Components/NetworkRigidbody.html")]
+ public class NetworkRigidbody : NetworkBehaviour
+ {
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkRigidbody));
+
+ [Header("Settings")]
+ [SerializeField] internal Rigidbody target = null;
+
+ [Tooltip("Set to true if moves come from owner client, set to false if moves always come from server")]
+ [SerializeField] bool clientAuthority = false;
+
+ [Header("Velocity")]
+
+ [Tooltip("Syncs Velocity every SyncInterval")]
+ [SerializeField] bool syncVelocity = true;
+
+ [Tooltip("Set velocity to 0 each frame (only works if syncVelocity is false")]
+ [SerializeField] bool clearVelocity = false;
+
+ [Tooltip("Only Syncs Value if distance between previous and current is great than sensitivity")]
+ [SerializeField] float velocitySensitivity = 0.1f;
+
+
+ [Header("Angular Velocity")]
+
+ [Tooltip("Syncs AngularVelocity every SyncInterval")]
+ [SerializeField] bool syncAngularVelocity = true;
+
+ [Tooltip("Set angularVelocity to 0 each frame (only works if syncAngularVelocity is false")]
+ [SerializeField] bool clearAngularVelocity = false;
+
+ [Tooltip("Only Syncs Value if distance between previous and current is great than sensitivity")]
+ [SerializeField] float angularVelocitySensitivity = 0.1f;
+
+ ///
+ /// Values sent on client with authoirty after they are sent to the server
+ ///
+ readonly ClientSyncState previousValue = new ClientSyncState();
+
+ void OnValidate()
+ {
+ if (target == null)
+ {
+ target = GetComponent();
+ }
+ }
+
+
+ #region Sync vars
+ [SyncVar(hook = nameof(OnVelocityChanged))]
+ Vector3 velocity;
+
+ [SyncVar(hook = nameof(OnAngularVelocityChanged))]
+ Vector3 angularVelocity;
+
+ [SyncVar(hook = nameof(OnIsKinematicChanged))]
+ bool isKinematic;
+
+ [SyncVar(hook = nameof(OnUseGravityChanged))]
+ bool useGravity;
+
+ [SyncVar(hook = nameof(OnuDragChanged))]
+ float drag;
+
+ [SyncVar(hook = nameof(OnAngularDragChanged))]
+ float angularDrag;
+
+ ///
+ /// Ignore value if is host or client with Authority
+ ///
+ ///
+ bool IgnoreSync => isServer || ClientWithAuthority;
+
+ bool ClientWithAuthority => clientAuthority && hasAuthority;
+
+ void OnVelocityChanged(Vector3 _, Vector3 newValue)
+ {
+ if (IgnoreSync)
+ return;
+
+ target.velocity = newValue;
+ }
+
+
+ void OnAngularVelocityChanged(Vector3 _, Vector3 newValue)
+ {
+ if (IgnoreSync)
+ return;
+
+ target.angularVelocity = newValue;
+ }
+
+ void OnIsKinematicChanged(bool _, bool newValue)
+ {
+ if (IgnoreSync)
+ return;
+
+ target.isKinematic = newValue;
+ }
+
+ void OnUseGravityChanged(bool _, bool newValue)
+ {
+ if (IgnoreSync)
+ return;
+
+ target.useGravity = newValue;
+ }
+
+ void OnuDragChanged(float _, float newValue)
+ {
+ if (IgnoreSync)
+ return;
+
+ target.drag = newValue;
+ }
+
+ void OnAngularDragChanged(float _, float newValue)
+ {
+ if (IgnoreSync)
+ return;
+
+ target.angularDrag = newValue;
+ }
+ #endregion
+
+
+ internal void Update()
+ {
+ if (isServer)
+ {
+ SyncToClients();
+ }
+ else if (ClientWithAuthority)
+ {
+ SendToServer();
+ }
+ }
+
+ internal void FixedUpdate()
+ {
+ if (clearAngularVelocity && !syncAngularVelocity)
+ {
+ target.angularVelocity = Vector3.zero;
+ }
+
+ if (clearVelocity && !syncVelocity)
+ {
+ target.velocity = Vector3.zero;
+ }
+ }
+
+ ///
+ /// Updates sync var values on server so that they sync to the client
+ ///
+ [Server]
+ void SyncToClients()
+ {
+ // only update if they have changed more than Sensitivity
+
+ Vector3 currentVelocity = syncVelocity ? target.velocity : default;
+ Vector3 currentAngularVelocity = syncAngularVelocity ? target.angularVelocity : default;
+
+ bool velocityChanged = syncVelocity && ((previousValue.velocity - currentVelocity).sqrMagnitude > velocitySensitivity * velocitySensitivity);
+ bool angularVelocityChanged = syncAngularVelocity && ((previousValue.angularVelocity - currentAngularVelocity).sqrMagnitude > angularVelocitySensitivity * angularVelocitySensitivity);
+
+ if (velocityChanged)
+ {
+ velocity = currentVelocity;
+ previousValue.velocity = currentVelocity;
+ }
+
+ if (angularVelocityChanged)
+ {
+ angularVelocity = currentAngularVelocity;
+ previousValue.angularVelocity = currentAngularVelocity;
+ }
+
+ // other rigidbody settings
+ isKinematic = target.isKinematic;
+ useGravity = target.useGravity;
+ drag = target.drag;
+ angularDrag = target.angularDrag;
+ }
+
+ ///
+ /// Uses Command to send values to server
+ ///
+ [Client]
+ void SendToServer()
+ {
+ if (!hasAuthority)
+ {
+ logger.LogWarning("SendToServer called without authority");
+ return;
+ }
+
+ SendVelocity();
+ SendRigidBodySettings();
+ }
+
+ [Client]
+ void SendVelocity()
+ {
+ float now = Time.time;
+ if (now < previousValue.nextSyncTime)
+ return;
+
+ Vector3 currentVelocity = syncVelocity ? target.velocity : default;
+ Vector3 currentAngularVelocity = syncAngularVelocity ? target.angularVelocity : default;
+
+ bool velocityChanged = syncVelocity && ((previousValue.velocity - currentVelocity).sqrMagnitude > velocitySensitivity * velocitySensitivity);
+ bool angularVelocityChanged = syncAngularVelocity && ((previousValue.angularVelocity - currentAngularVelocity).sqrMagnitude > angularVelocitySensitivity * angularVelocitySensitivity);
+
+ // if angularVelocity has changed it is likely that velocity has also changed so just sync both values
+ // however if only velocity has changed just send velocity
+ if (angularVelocityChanged)
+ {
+ CmdSendVelocityAndAngular(currentVelocity, currentAngularVelocity);
+ previousValue.velocity = currentVelocity;
+ previousValue.angularVelocity = currentAngularVelocity;
+ }
+ else if (velocityChanged)
+ {
+ CmdSendVelocity(currentVelocity);
+ previousValue.velocity = currentVelocity;
+ }
+
+
+ // only update syncTime if either has changed
+ if (angularVelocityChanged || velocityChanged)
+ {
+ previousValue.nextSyncTime = now + syncInterval;
+ }
+ }
+
+ [Client]
+ void SendRigidBodySettings()
+ {
+ // These shouldn't change often so it is ok to send in their own Command
+ if (previousValue.isKinematic != target.isKinematic)
+ {
+ CmdSendIsKinematic(target.isKinematic);
+ previousValue.isKinematic = target.isKinematic;
+ }
+ if (previousValue.useGravity != target.useGravity)
+ {
+ CmdSendUseGravity(target.useGravity);
+ previousValue.useGravity = target.useGravity;
+ }
+ if (previousValue.drag != target.drag)
+ {
+ CmdSendDrag(target.drag);
+ previousValue.drag = target.drag;
+ }
+ if (previousValue.angularDrag != target.angularDrag)
+ {
+ CmdSendAngularDrag(target.angularDrag);
+ previousValue.angularDrag = target.angularDrag;
+ }
+ }
+
+ ///
+ /// Called when only Velocity has changed on the client
+ ///
+ [Command]
+ void CmdSendVelocity(Vector3 velocity)
+ {
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
+ this.velocity = velocity;
+ target.velocity = velocity;
+ }
+
+ ///
+ /// Called when angularVelocity has changed on the client
+ ///
+ [Command]
+ void CmdSendVelocityAndAngular(Vector3 velocity, Vector3 angularVelocity)
+ {
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
+ if (syncVelocity)
+ {
+ this.velocity = velocity;
+
+ target.velocity = velocity;
+
+ }
+ this.angularVelocity = angularVelocity;
+ target.angularVelocity = angularVelocity;
+ }
+
+ [Command]
+ void CmdSendIsKinematic(bool isKinematic)
+ {
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
+ this.isKinematic = isKinematic;
+ target.isKinematic = isKinematic;
+ }
+
+ [Command]
+ void CmdSendUseGravity(bool useGravity)
+ {
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
+ this.useGravity = useGravity;
+ target.useGravity = useGravity;
+ }
+
+ [Command]
+ void CmdSendDrag(float drag)
+ {
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
+ this.drag = drag;
+ target.drag = drag;
+ }
+
+ [Command]
+ void CmdSendAngularDrag(float angularDrag)
+ {
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
+ this.angularDrag = angularDrag;
+ target.angularDrag = angularDrag;
+ }
+
+ ///
+ /// holds previously synced values
+ ///
+ public class ClientSyncState
+ {
+ ///
+ /// Next sync time that velocity will be synced, based on syncInterval.
+ ///
+ public float nextSyncTime;
+ public Vector3 velocity;
+ public Vector3 angularVelocity;
+ public bool isKinematic;
+ public bool useGravity;
+ public float drag;
+ public float angularDrag;
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkRigidbody.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkRigidbody.cs.meta
new file mode 100644
index 0000000..1610f0a
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkRigidbody.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 83392ae5c1b731446909f252fd494ae4
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransform.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransform.cs
new file mode 100644
index 0000000..288a5e6
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransform.cs
@@ -0,0 +1,12 @@
+using UnityEngine;
+
+namespace Mirror.Experimental
+{
+ [DisallowMultipleComponent]
+ [AddComponentMenu("Network/Experimental/NetworkTransformExperimental")]
+ [HelpURL("https://mirror-networking.com/docs/Components/NetworkTransform.html")]
+ public class NetworkTransform : NetworkTransformBase
+ {
+ protected override Transform targetTransform => transform;
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransform.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransform.cs.meta
new file mode 100644
index 0000000..2bc16dd
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransform.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 741bbe11f5357b44593b15c0d11b16bd
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformBase.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformBase.cs
new file mode 100644
index 0000000..bd33d08
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformBase.cs
@@ -0,0 +1,430 @@
+// vis2k:
+// base class for NetworkTransform and NetworkTransformChild.
+// New method is simple and stupid. No more 1500 lines of code.
+//
+// Server sends current data.
+// Client saves it and interpolates last and latest data points.
+// Update handles transform movement / rotation
+// FixedUpdate handles rigidbody movement / rotation
+//
+// Notes:
+// * Built-in Teleport detection in case of lags / teleport / obstacles
+// * Quaternion > EulerAngles because gimbal lock and Quaternion.Slerp
+// * Syncs XYZ. Works 3D and 2D. Saving 4 bytes isn't worth 1000 lines of code.
+// * Initial delay might happen if server sends packet immediately after moving
+// just 1cm, hence we move 1cm and then wait 100ms for next packet
+// * Only way for smooth movement is to use a fixed movement speed during
+// interpolation. interpolation over time is never that good.
+//
+using System;
+using UnityEngine;
+
+namespace Mirror.Experimental
+{
+ public abstract class NetworkTransformBase : NetworkBehaviour
+ {
+ // target transform to sync. can be on a child.
+ protected abstract Transform targetTransform { get; }
+
+ [Header("Authority")]
+
+ [Tooltip("Set to true if moves come from owner client, set to false if moves always come from server")]
+ [SyncVar]
+ public bool clientAuthority;
+
+ [Tooltip("Set to true if updates from server should be ignored by owner")]
+ [SyncVar]
+ public bool excludeOwnerUpdate = true;
+
+ [Header("Synchronization")]
+
+ [Tooltip("Set to true if position should be synchronized")]
+ [SyncVar]
+ public bool syncPosition = true;
+
+ [Tooltip("Set to true if rotation should be synchronized")]
+ [SyncVar]
+ public bool syncRotation = true;
+
+ [Tooltip("Set to true if scale should be synchronized")]
+ [SyncVar]
+ public bool syncScale = true;
+
+ [Header("Interpolation")]
+
+ [Tooltip("Set to true if position should be interpolated")]
+ [SyncVar]
+ public bool interpolatePosition = true;
+
+ [Tooltip("Set to true if rotation should be interpolated")]
+ [SyncVar]
+ public bool interpolateRotation = true;
+
+ [Tooltip("Set to true if scale should be interpolated")]
+ [SyncVar]
+ public bool interpolateScale = true;
+
+ // Sensitivity is added for VR where human players tend to have micro movements so this can quiet down
+ // the network traffic. Additionally, rigidbody drift should send less traffic, e.g very slow sliding / rolling.
+ [Header("Sensitivity")]
+
+ [Tooltip("Changes to the transform must exceed these values to be transmitted on the network.")]
+ [SyncVar]
+ public float localPositionSensitivity = .01f;
+
+ [Tooltip("If rotation exceeds this angle, it will be transmitted on the network")]
+ [SyncVar]
+ public float localRotationSensitivity = .01f;
+
+ [Tooltip("Changes to the transform must exceed these values to be transmitted on the network.")]
+ [SyncVar]
+ public float localScaleSensitivity = .01f;
+
+ [Header("Diagnostics")]
+
+ // server
+ public Vector3 lastPosition;
+ public Quaternion lastRotation;
+ public Vector3 lastScale;
+
+ // client
+ // use local position/rotation for VR support
+ [Serializable]
+ public struct DataPoint
+ {
+ public float timeStamp;
+ public Vector3 localPosition;
+ public Quaternion localRotation;
+ public Vector3 localScale;
+ public float movementSpeed;
+
+ public bool isValid => timeStamp != 0;
+ }
+
+ // Is this a client with authority over this transform?
+ // This component could be on the player object or any object that has been assigned authority to this client.
+ bool IsOwnerWithClientAuthority => hasAuthority && clientAuthority;
+
+ // interpolation start and goal
+ public DataPoint start = new DataPoint();
+ public DataPoint goal = new DataPoint();
+
+ void FixedUpdate()
+ {
+ // if server then always sync to others.
+ // let the clients know that this has moved
+ if (isServer && HasEitherMovedRotatedScaled())
+ {
+ RpcMove(targetTransform.localPosition, targetTransform.localRotation, targetTransform.localScale);
+ }
+
+ if (isClient)
+ {
+ // send to server if we have local authority (and aren't the server)
+ // -> only if connectionToServer has been initialized yet too
+ if (IsOwnerWithClientAuthority)
+ {
+ if (!isServer && HasEitherMovedRotatedScaled())
+ {
+ // serialize
+ // local position/rotation for VR support
+ // send to server
+ CmdClientToServerSync(targetTransform.localPosition, targetTransform.localRotation, targetTransform.localScale);
+ }
+ }
+ else if (goal.isValid)
+ {
+ // teleport or interpolate
+ if (NeedsTeleport())
+ {
+ // local position/rotation for VR support
+ ApplyPositionRotationScale(goal.localPosition, goal.localRotation, goal.localScale);
+
+ // reset data points so we don't keep interpolating
+ start = new DataPoint();
+ goal = new DataPoint();
+ }
+ else
+ {
+ // local position/rotation for VR support
+ ApplyPositionRotationScale(InterpolatePosition(start, goal, targetTransform.localPosition),
+ InterpolateRotation(start, goal, targetTransform.localRotation),
+ InterpolateScale(start, goal, targetTransform.localScale));
+ }
+
+ }
+ }
+ }
+
+ // moved or rotated or scaled since last time we checked it?
+ bool HasEitherMovedRotatedScaled()
+ {
+ // Save last for next frame to compare only if change was detected, otherwise
+ // slow moving objects might never sync because of C#'s float comparison tolerance.
+ // See also: https://github.com/vis2k/Mirror/pull/428)
+ bool changed = HasMoved || HasRotated || HasScaled;
+ if (changed)
+ {
+ // local position/rotation for VR support
+ if (syncPosition) lastPosition = targetTransform.localPosition;
+ if (syncRotation) lastRotation = targetTransform.localRotation;
+ if (syncScale) lastScale = targetTransform.localScale;
+ }
+ return changed;
+ }
+
+ // local position/rotation for VR support
+ // SqrMagnitude is faster than Distance per Unity docs
+ // https://docs.unity3d.com/ScriptReference/Vector3-sqrMagnitude.html
+
+ bool HasMoved => syncPosition && Vector3.SqrMagnitude(lastPosition - targetTransform.localPosition) > localPositionSensitivity * localPositionSensitivity;
+ bool HasRotated => syncRotation && Quaternion.Angle(lastRotation, targetTransform.localRotation) > localRotationSensitivity;
+ bool HasScaled => syncScale && Vector3.SqrMagnitude(lastScale - targetTransform.localScale) > localScaleSensitivity * localScaleSensitivity;
+
+ // teleport / lag / stuck detection
+ // - checking distance is not enough since there could be just a tiny fence between us and the goal
+ // - checking time always works, this way we just teleport if we still didn't reach the goal after too much time has elapsed
+ bool NeedsTeleport()
+ {
+ // calculate time between the two data points
+ float startTime = start.isValid ? start.timeStamp : Time.time - Time.fixedDeltaTime;
+ float goalTime = goal.isValid ? goal.timeStamp : Time.time;
+ float difference = goalTime - startTime;
+ float timeSinceGoalReceived = Time.time - goalTime;
+ return timeSinceGoalReceived > difference * 5;
+ }
+
+ // local authority client sends sync message to server for broadcasting
+ [Command]
+ void CmdClientToServerSync(Vector3 position, Quaternion rotation, Vector3 scale)
+ {
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
+ // deserialize payload
+ SetGoal(position, rotation, scale);
+
+ // server-only mode does no interpolation to save computations, but let's set the position directly
+ if (isServer && !isClient)
+ ApplyPositionRotationScale(goal.localPosition, goal.localRotation, goal.localScale);
+
+ RpcMove(position, rotation, scale);
+ }
+
+ [ClientRpc]
+ void RpcMove(Vector3 position, Quaternion rotation, Vector3 scale)
+ {
+ if (hasAuthority && excludeOwnerUpdate) return;
+
+ if (!isServer)
+ SetGoal(position, rotation, scale);
+ }
+
+ // serialization is needed by OnSerialize and by manual sending from authority
+ void SetGoal(Vector3 position, Quaternion rotation, Vector3 scale)
+ {
+ // put it into a data point immediately
+ DataPoint temp = new DataPoint
+ {
+ // deserialize position
+ localPosition = position,
+ localRotation = rotation,
+ localScale = scale,
+ timeStamp = Time.time
+ };
+
+ // movement speed: based on how far it moved since last time has to be calculated before 'start' is overwritten
+ temp.movementSpeed = EstimateMovementSpeed(goal, temp, targetTransform, Time.fixedDeltaTime);
+
+ // reassign start wisely
+ // first ever data point? then make something up for previous one so that we can start interpolation without waiting for next.
+ if (start.timeStamp == 0)
+ {
+ start = new DataPoint
+ {
+ timeStamp = Time.time - Time.fixedDeltaTime,
+ // local position/rotation for VR support
+ localPosition = targetTransform.localPosition,
+ localRotation = targetTransform.localRotation,
+ localScale = targetTransform.localScale,
+ movementSpeed = temp.movementSpeed
+ };
+ }
+ // second or nth data point? then update previous
+ // but: we start at where ever we are right now, so that it's perfectly smooth and we don't jump anywhere
+ //
+ // example if we are at 'x':
+ //
+ // A--x->B
+ //
+ // and then receive a new point C:
+ //
+ // A--x--B
+ // |
+ // |
+ // C
+ //
+ // then we don't want to just jump to B and start interpolation:
+ //
+ // x
+ // |
+ // |
+ // C
+ //
+ // we stay at 'x' and interpolate from there to C:
+ //
+ // x..B
+ // \ .
+ // \.
+ // C
+ //
+ else
+ {
+ float oldDistance = Vector3.Distance(start.localPosition, goal.localPosition);
+ float newDistance = Vector3.Distance(goal.localPosition, temp.localPosition);
+
+ start = goal;
+
+ // local position/rotation for VR support
+ // teleport / lag / obstacle detection: only continue at current position if we aren't too far away
+ // XC < AB + BC (see comments above)
+ if (Vector3.Distance(targetTransform.localPosition, start.localPosition) < oldDistance + newDistance)
+ {
+ start.localPosition = targetTransform.localPosition;
+ start.localRotation = targetTransform.localRotation;
+ start.localScale = targetTransform.localScale;
+ }
+ }
+
+ // set new destination in any case. new data is best data.
+ goal = temp;
+ }
+
+ // try to estimate movement speed for a data point based on how far it moved since the previous one
+ // - if this is the first time ever then we use our best guess:
+ // - delta based on transform.localPosition
+ // - elapsed based on send interval hoping that it roughly matches
+ static float EstimateMovementSpeed(DataPoint from, DataPoint to, Transform transform, float sendInterval)
+ {
+ Vector3 delta = to.localPosition - (from.localPosition != transform.localPosition ? from.localPosition : transform.localPosition);
+ float elapsed = from.isValid ? to.timeStamp - from.timeStamp : sendInterval;
+
+ // avoid NaN
+ return elapsed > 0 ? delta.magnitude / elapsed : 0;
+ }
+
+ // set position carefully depending on the target component
+ void ApplyPositionRotationScale(Vector3 position, Quaternion rotation, Vector3 scale)
+ {
+ // local position/rotation for VR support
+ if (syncPosition) targetTransform.localPosition = position;
+ if (syncRotation) targetTransform.localRotation = rotation;
+ if (syncScale) targetTransform.localScale = scale;
+ }
+
+ // where are we in the timeline between start and goal? [0,1]
+ Vector3 InterpolatePosition(DataPoint start, DataPoint goal, Vector3 currentPosition)
+ {
+ if (!interpolatePosition)
+ return currentPosition;
+
+ if (start.movementSpeed != 0)
+ {
+ // Option 1: simply interpolate based on time, but stutter will happen, it's not that smooth.
+ // This is especially noticeable if the camera automatically follows the player
+ // - Tell SonarCloud this isn't really commented code but actual comments and to stfu about it
+ // - float t = CurrentInterpolationFactor();
+ // - return Vector3.Lerp(start.position, goal.position, t);
+
+ // Option 2: always += speed
+ // speed is 0 if we just started after idle, so always use max for best results
+ float speed = Mathf.Max(start.movementSpeed, goal.movementSpeed);
+ return Vector3.MoveTowards(currentPosition, goal.localPosition, speed * Time.deltaTime);
+ }
+
+ return currentPosition;
+ }
+
+ Quaternion InterpolateRotation(DataPoint start, DataPoint goal, Quaternion defaultRotation)
+ {
+ if (!interpolateRotation)
+ return defaultRotation;
+
+ if (start.localRotation != goal.localRotation)
+ {
+ float t = CurrentInterpolationFactor(start, goal);
+ return Quaternion.Slerp(start.localRotation, goal.localRotation, t);
+ }
+
+ return defaultRotation;
+ }
+
+ Vector3 InterpolateScale(DataPoint start, DataPoint goal, Vector3 currentScale)
+ {
+ if (!interpolateScale)
+ return currentScale;
+
+ if (start.localScale != goal.localScale)
+ {
+ float t = CurrentInterpolationFactor(start, goal);
+ return Vector3.Lerp(start.localScale, goal.localScale, t);
+ }
+
+ return currentScale;
+ }
+
+ static float CurrentInterpolationFactor(DataPoint start, DataPoint goal)
+ {
+ if (start.isValid)
+ {
+ float difference = goal.timeStamp - start.timeStamp;
+
+ // the moment we get 'goal', 'start' is supposed to start, so elapsed time is based on:
+ float elapsed = Time.time - goal.timeStamp;
+
+ // avoid NaN
+ return difference > 0 ? elapsed / difference : 1;
+ }
+ return 1;
+ }
+
+ #region Debug Gizmos
+
+ // draw the data points for easier debugging
+ void OnDrawGizmos()
+ {
+ // draw start and goal points and a line between them
+ if (start.localPosition != goal.localPosition)
+ {
+ DrawDataPointGizmo(start, Color.yellow);
+ DrawDataPointGizmo(goal, Color.green);
+ DrawLineBetweenDataPoints(start, goal, Color.cyan);
+ }
+ }
+
+ static void DrawDataPointGizmo(DataPoint data, Color color)
+ {
+ // use a little offset because transform.localPosition might be in the ground in many cases
+ Vector3 offset = Vector3.up * 0.01f;
+
+ // draw position
+ Gizmos.color = color;
+ Gizmos.DrawSphere(data.localPosition + offset, 0.5f);
+
+ // draw forward and up like unity move tool
+ Gizmos.color = Color.blue;
+ Gizmos.DrawRay(data.localPosition + offset, data.localRotation * Vector3.forward);
+ Gizmos.color = Color.green;
+ Gizmos.DrawRay(data.localPosition + offset, data.localRotation * Vector3.up);
+ }
+
+ static void DrawLineBetweenDataPoints(DataPoint data1, DataPoint data2, Color color)
+ {
+ Gizmos.color = color;
+ Gizmos.DrawLine(data1.localPosition, data2.localPosition);
+ }
+
+ #endregion
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformBase.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformBase.cs.meta
new file mode 100644
index 0000000..d737bed
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformBase.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ea7c690c4fbf8c4439726f4c62eda6d3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformChild.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformChild.cs
new file mode 100644
index 0000000..4494bd1
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformChild.cs
@@ -0,0 +1,18 @@
+using UnityEngine;
+
+namespace Mirror.Experimental
+{
+ ///
+ /// A component to synchronize the position of child transforms of networked objects.
+ /// There must be a NetworkTransform on the root object of the hierarchy. There can be multiple NetworkTransformChild components on an object. This does not use physics for synchronization, it simply synchronizes the localPosition and localRotation of the child transform and lerps towards the recieved values.
+ ///
+ [AddComponentMenu("Network/Experimental/NetworkTransformChildExperimentalExperimental")]
+ [HelpURL("https://mirror-networking.com/docs/Components/NetworkTransformChild.html")]
+ public class NetworkTransformChild : NetworkTransformBase
+ {
+ [Header("Target")]
+ public Transform target;
+
+ protected override Transform targetTransform => target;
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformChild.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformChild.cs.meta
new file mode 100644
index 0000000..30f0d89
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/Experimental/NetworkTransformChild.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f65214da13a861f4a8ae309d3daea1c6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkAnimator.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkAnimator.cs
index f3b472b..912f8d6 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkAnimator.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkAnimator.cs
@@ -1,4 +1,4 @@
-using System;
+using System.Linq;
using UnityEngine;
using UnityEngine.Serialization;
@@ -9,20 +9,27 @@ namespace Mirror
///
///
/// The animation of game objects can be networked by this component. There are two models of authority for networked movement:
- /// If the object has authority on the client, then it should animated locally on the owning client. The animation state information will be sent from the owning client to the server, then broadcast to all of the other clients. This is common for player objects.
+ /// If the object has authority on the client, then it should be animated locally on the owning client. The animation state information will be sent from the owning client to the server, then broadcast to all of the other clients. This is common for player objects.
/// If the object has authority on the server, then it should be animated on the server and state information will be sent to all clients. This is common for objects not related to a specific client, such as an enemy unit.
- /// The NetworkAnimator synchronizes the animation parameters that are checked in the inspector view. It does not automatically sychronize triggers. The function SetTrigger can by used by an object with authority to fire an animation trigger on other clients.
+ /// The NetworkAnimator synchronizes all animation parameters of the selected Animator. It does not automatically sychronize triggers. The function SetTrigger can by used by an object with authority to fire an animation trigger on other clients.
///
- [DisallowMultipleComponent]
[AddComponentMenu("Network/NetworkAnimator")]
[RequireComponent(typeof(NetworkIdentity))]
[HelpURL("https://mirror-networking.com/docs/Components/NetworkAnimator.html")]
public class NetworkAnimator : NetworkBehaviour
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkAnimator));
+
+ [Header("Authority")]
+ [Tooltip("Set to true if animations come from owner client, set to false if animations always come from server")]
+ public bool clientAuthority;
+
///
/// The animator component to synchronize.
///
[FormerlySerializedAs("m_Animator")]
+ [Header("Animator")]
+ [Tooltip("Animator that will have parameters synchronized")]
public Animator animator;
// Note: not an object[] array because otherwise initialization is real annoying
@@ -31,30 +38,30 @@ public class NetworkAnimator : NetworkBehaviour
bool[] lastBoolParameters;
AnimatorControllerParameter[] parameters;
- int[] animationHash; // multiple layers
+ // multiple layers
+ int[] animationHash;
int[] transitionHash;
- float sendTimer;
+ float nextSendTime;
- bool sendMessagesAllowed
+ bool SendMessagesAllowed
{
get
{
if (isServer)
{
- if (!localPlayerAuthority)
+ if (!clientAuthority)
return true;
- // This is a special case where we have localPlayerAuthority set
- // on a NetworkIdentity but we have not assigned the client who has
+ // This is a special case where we have client authority but we have not assigned the client who has
// authority over it, no animator data will be sent over the network by the server.
//
- // So we check here for a clientAuthorityOwner and if it is null we will
+ // So we check here for a connectionToClient and if it is null we will
// let the server send animation data until we receive an owner.
- if (netIdentity != null && netIdentity.clientAuthorityOwner == null)
+ if (netIdentity != null && netIdentity.connectionToClient == null)
return true;
}
- return hasAuthority;
+ return (hasAuthority && clientAuthority);
}
}
@@ -62,7 +69,9 @@ void Awake()
{
// store the animator parameters in a variable - the "Animator.parameters" getter allocates
// a new parameter array every time it is accessed so we should avoid doing it in a loop
- parameters = animator.parameters;
+ parameters = animator.parameters
+ .Where(par => !animator.IsParameterControlledByCurve(par.nameHash))
+ .ToArray();
lastIntParameters = new int[parameters.Length];
lastFloatParameters = new float[parameters.Length];
lastBoolParameters = new bool[parameters.Length];
@@ -73,7 +82,10 @@ void Awake()
void FixedUpdate()
{
- if (!sendMessagesAllowed)
+ if (!SendMessagesAllowed)
+ return;
+
+ if (!animator.enabled)
return;
CheckSendRate();
@@ -87,11 +99,11 @@ void FixedUpdate()
continue;
}
- NetworkWriter writer = NetworkWriterPool.GetWriter();
- WriteParameters(writer);
-
- SendAnimationMessage(stateHash, normalizedTime, i, writer.ToArraySegment());
- NetworkWriterPool.Recycle(writer);
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
+ {
+ WriteParameters(writer);
+ SendAnimationMessage(stateHash, normalizedTime, i, writer.ToArray());
+ }
}
}
@@ -132,20 +144,20 @@ bool CheckAnimStateChanged(out int stateHash, out float normalizedTime, int laye
void CheckSendRate()
{
- if (sendMessagesAllowed && syncInterval != 0 && sendTimer < Time.time)
+ float now = Time.time;
+ if (SendMessagesAllowed && syncInterval >= 0 && now > nextSendTime)
{
- sendTimer = Time.time + syncInterval;
+ nextSendTime = now + syncInterval;
- NetworkWriter writer = NetworkWriterPool.GetWriter();
- if (WriteParameters(writer))
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
{
- SendAnimationParametersMessage(writer.ToArraySegment());
+ if (WriteParameters(writer))
+ SendAnimationParametersMessage(writer.ToArray());
}
- NetworkWriterPool.Recycle(writer);
}
}
- void SendAnimationMessage(int stateHash, float normalizedTime, int layerId, ArraySegment parameters)
+ void SendAnimationMessage(int stateHash, float normalizedTime, int layerId, byte[] parameters)
{
if (isServer)
{
@@ -157,7 +169,7 @@ void SendAnimationMessage(int stateHash, float normalizedTime, int layerId, Arra
}
}
- void SendAnimationParametersMessage(ArraySegment parameters)
+ void SendAnimationParametersMessage(byte[] parameters)
{
if (isServer)
{
@@ -171,13 +183,13 @@ void SendAnimationParametersMessage(ArraySegment parameters)
void HandleAnimMsg(int stateHash, float normalizedTime, int layerId, NetworkReader reader)
{
- if (hasAuthority)
+ if (hasAuthority && clientAuthority)
return;
// usually transitions will be triggered by parameters, if not, play anims directly.
// NOTE: this plays "animations", not transitions, so any transitions will be skipped.
// NOTE: there is no API to play a transition(?)
- if (stateHash != 0)
+ if (stateHash != 0 && animator.enabled)
{
animator.Play(stateHash, layerId, normalizedTime);
}
@@ -187,7 +199,7 @@ void HandleAnimMsg(int stateHash, float normalizedTime, int layerId, NetworkRead
void HandleAnimParamsMsg(NetworkReader reader)
{
- if (hasAuthority)
+ if (hasAuthority && clientAuthority)
return;
ReadParameters(reader);
@@ -195,7 +207,14 @@ void HandleAnimParamsMsg(NetworkReader reader)
void HandleAnimTriggerMsg(int hash)
{
- animator.SetTrigger(hash);
+ if (animator.enabled)
+ animator.SetTrigger(hash);
+ }
+
+ void HandleAnimResetTriggerMsg(int hash)
+ {
+ if (animator.enabled)
+ animator.ResetTrigger(hash);
}
ulong NextDirtyBits()
@@ -210,27 +229,22 @@ ulong NextDirtyBits()
int newIntValue = animator.GetInteger(par.nameHash);
changed = newIntValue != lastIntParameters[i];
if (changed)
- {
lastIntParameters[i] = newIntValue;
- }
}
else if (par.type == AnimatorControllerParameterType.Float)
{
float newFloatValue = animator.GetFloat(par.nameHash);
changed = Mathf.Abs(newFloatValue - lastFloatParameters[i]) > 0.001f;
+ // only set lastValue if it was changed, otherwise value could slowly drift within the 0.001f limit each frame
if (changed)
- {
lastFloatParameters[i] = newFloatValue;
- }
}
else if (par.type == AnimatorControllerParameterType.Bool)
{
bool newBoolValue = animator.GetBool(par.nameHash);
changed = newBoolValue != lastBoolParameters[i];
if (changed)
- {
lastBoolParameters[i] = newBoolValue;
- }
}
if (changed)
{
@@ -271,6 +285,9 @@ bool WriteParameters(NetworkWriter writer, bool forceAll = false)
void ReadParameters(NetworkReader reader)
{
+ bool animatorEnabled = animator.enabled;
+ // need to read values from NetworkReader even if animator is disabled
+
ulong dirtyBits = reader.ReadPackedUInt64();
for (int i = 0; i < parameters.Length; i++)
{
@@ -281,17 +298,20 @@ void ReadParameters(NetworkReader reader)
if (par.type == AnimatorControllerParameterType.Int)
{
int newIntValue = reader.ReadPackedInt32();
- animator.SetInteger(par.nameHash, newIntValue);
+ if (animatorEnabled)
+ animator.SetInteger(par.nameHash, newIntValue);
}
else if (par.type == AnimatorControllerParameterType.Float)
{
float newFloatValue = reader.ReadSingle();
- animator.SetFloat(par.nameHash, newFloatValue);
+ if (animatorEnabled)
+ animator.SetFloat(par.nameHash, newFloatValue);
}
else if (par.type == AnimatorControllerParameterType.Bool)
{
bool newBoolValue = reader.ReadBoolean();
- animator.SetBool(par.nameHash, newBoolValue);
+ if (animatorEnabled)
+ animator.SetBool(par.nameHash, newBoolValue);
}
}
}
@@ -300,11 +320,11 @@ void ReadParameters(NetworkReader reader)
/// Custom Serialization
///
///
- ///
+ ///
///
- public override bool OnSerialize(NetworkWriter writer, bool forceAll)
+ public override bool OnSerialize(NetworkWriter writer, bool initialState)
{
- if (forceAll)
+ if (initialState)
{
for (int i = 0; i < animator.layerCount; i++)
{
@@ -321,7 +341,7 @@ public override bool OnSerialize(NetworkWriter writer, bool forceAll)
writer.WriteSingle(st.normalizedTime);
}
}
- WriteParameters(writer, forceAll);
+ WriteParameters(writer, initialState);
return true;
}
return false;
@@ -363,76 +383,176 @@ public void SetTrigger(string triggerName)
/// Hash id of trigger (from the Animator).
public void SetTrigger(int hash)
{
- if (hasAuthority && localPlayerAuthority)
+ if (clientAuthority)
{
- if (ClientScene.readyConnection != null)
+ if (!isClient)
{
+ logger.LogWarning("Tried to set animation in the server for a client-controlled animator");
+ return;
+ }
+
+ if (!hasAuthority)
+ {
+ logger.LogWarning("Only the client with authority can set animations");
+ return;
+ }
+
+ if (ClientScene.readyConnection != null)
CmdOnAnimationTriggerServerMessage(hash);
+ }
+ else
+ {
+ if (!isServer)
+ {
+ logger.LogWarning("Tried to set animation in the client for a server-controlled animator");
+ return;
}
- return;
+
+ HandleAnimTriggerMsg(hash);
+ RpcOnAnimationTriggerClientMessage(hash);
}
+ }
- if (isServer && !localPlayerAuthority)
+ ///
+ /// Causes an animation trigger to be reset for a networked object.
+ /// If local authority is set, and this is called from the client, then the trigger will be reset on the server and all clients. If not, then this is called on the server, and the trigger will be reset on all clients.
+ ///
+ /// Name of trigger.
+ public void ResetTrigger(string triggerName)
+ {
+ ResetTrigger(Animator.StringToHash(triggerName));
+ }
+
+ ///
+ /// Causes an animation trigger to be reset for a networked object.
+ ///
+ /// Hash id of trigger (from the Animator).
+ public void ResetTrigger(int hash)
+ {
+ if (clientAuthority)
{
- RpcOnAnimationTriggerClientMessage(hash);
+ if (!isClient)
+ {
+ logger.LogWarning("Tried to reset animation in the server for a client-controlled animator");
+ return;
+ }
+
+ if (!hasAuthority)
+ {
+ logger.LogWarning("Only the client with authority can reset animations");
+ return;
+ }
+
+ if (ClientScene.readyConnection != null)
+ CmdOnAnimationResetTriggerServerMessage(hash);
+ }
+ else
+ {
+ if (!isServer)
+ {
+ logger.LogWarning("Tried to reset animation in the client for a server-controlled animator");
+ return;
+ }
+
+ HandleAnimResetTriggerMsg(hash);
+ RpcOnAnimationResetTriggerClientMessage(hash);
}
}
#region server message handlers
+
[Command]
- void CmdOnAnimationServerMessage(int stateHash, float normalizedTime, int layerId, ArraySegment parameters)
+ void CmdOnAnimationServerMessage(int stateHash, float normalizedTime, int layerId, byte[] parameters)
{
- if (LogFilter.Debug) Debug.Log("OnAnimationMessage for netId=" + netId);
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
+ if (logger.LogEnabled()) logger.Log("OnAnimationMessage for netId=" + netId);
// handle and broadcast
- NetworkReader reader = NetworkReaderPool.GetReader(parameters);
- HandleAnimMsg(stateHash, normalizedTime, layerId, reader);
- NetworkReaderPool.Recycle(reader);
- RpcOnAnimationClientMessage(stateHash, normalizedTime, layerId, parameters);
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(parameters))
+ {
+ HandleAnimMsg(stateHash, normalizedTime, layerId, networkReader);
+ RpcOnAnimationClientMessage(stateHash, normalizedTime, layerId, parameters);
+ }
}
[Command]
- void CmdOnAnimationParametersServerMessage(ArraySegment parameters)
+ void CmdOnAnimationParametersServerMessage(byte[] parameters)
{
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
// handle and broadcast
- NetworkReader reader = NetworkReaderPool.GetReader(parameters);
- HandleAnimParamsMsg(reader);
- NetworkReaderPool.Recycle(reader);
- RpcOnAnimationParametersClientMessage(parameters);
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(parameters))
+ {
+ HandleAnimParamsMsg(networkReader);
+ RpcOnAnimationParametersClientMessage(parameters);
+ }
}
[Command]
void CmdOnAnimationTriggerServerMessage(int hash)
{
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
// handle and broadcast
HandleAnimTriggerMsg(hash);
RpcOnAnimationTriggerClientMessage(hash);
}
+
+ [Command]
+ void CmdOnAnimationResetTriggerServerMessage(int hash)
+ {
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
+ // handle and broadcast
+ HandleAnimResetTriggerMsg(hash);
+ RpcOnAnimationResetTriggerClientMessage(hash);
+ }
+
#endregion
#region client message handlers
+
[ClientRpc]
- void RpcOnAnimationClientMessage(int stateHash, float normalizedTime, int layerId, ArraySegment parameters)
+ void RpcOnAnimationClientMessage(int stateHash, float normalizedTime, int layerId, byte[] parameters)
{
- NetworkReader reader = NetworkReaderPool.GetReader(parameters);
- HandleAnimMsg(stateHash, normalizedTime, layerId, reader);
- NetworkReaderPool.Recycle(reader);
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(parameters))
+ HandleAnimMsg(stateHash, normalizedTime, layerId, networkReader);
}
[ClientRpc]
- void RpcOnAnimationParametersClientMessage(ArraySegment parameters)
+ void RpcOnAnimationParametersClientMessage(byte[] parameters)
{
- NetworkReader reader = NetworkReaderPool.GetReader(parameters);
- HandleAnimParamsMsg(reader);
- NetworkReaderPool.Recycle(reader);
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(parameters))
+ HandleAnimParamsMsg(networkReader);
}
- // server sends this to one client
[ClientRpc]
void RpcOnAnimationTriggerClientMessage(int hash)
{
+ // host handles this before it is sent
+ if (isServer) return;
+
HandleAnimTriggerMsg(hash);
}
+
+ [ClientRpc]
+ void RpcOnAnimationResetTriggerClientMessage(int hash)
+ {
+ // host handles this before it is sent
+ if (isServer) return;
+
+ HandleAnimResetTriggerMsg(hash);
+ }
+
#endregion
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkAnimator.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkAnimator.cs.meta
index 5fb8576..211ce78 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkAnimator.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkAnimator.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyManager.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyManager.cs
index 3c581d3..5301e39 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyManager.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyManager.cs
@@ -1,9 +1,5 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
using UnityEngine;
-using UnityEngine.SceneManagement;
-using UnityEngine.Serialization;
namespace Mirror
{
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyManager.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyManager.cs.meta
index 317d79f..a32c8c7 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyManager.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyManager.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyPlayer.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyPlayer.cs
index 2dfef69..2e65465 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyPlayer.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyPlayer.cs
@@ -1,6 +1,5 @@
using System;
using UnityEngine;
-using UnityEngine.SceneManagement;
namespace Mirror
{
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyPlayer.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyPlayer.cs.meta
index 12a19d3..7a21eec 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyPlayer.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkLobbyPlayer.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkMatchChecker.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkMatchChecker.cs
new file mode 100644
index 0000000..c3e949c
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkMatchChecker.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Mirror
+{
+ ///
+ /// Component that controls visibility of networked objects based on match id.
+ /// Any object with this component on it will only be visible to other objects in the same match.
+ /// This would be used to isolate players to their respective matches within a single game server instance.
+ ///
+ [DisallowMultipleComponent]
+ [AddComponentMenu("Network/NetworkMatchChecker")]
+ [RequireComponent(typeof(NetworkIdentity))]
+ [HelpURL("https://mirror-networking.com/docs/Components/NetworkMatchChecker.html")]
+ public class NetworkMatchChecker : NetworkVisibility
+ {
+ static readonly Dictionary> matchPlayers = new Dictionary>();
+
+ Guid currentMatch = Guid.Empty;
+
+ [Header("Diagnostics")]
+ [SyncVar]
+ public string currentMatchDebug;
+
+ ///
+ /// Set this to the same value on all networked objects that belong to a given match
+ ///
+ public Guid matchId
+ {
+ get { return currentMatch; }
+ set
+ {
+ if (currentMatch == value) return;
+
+ // cache previous match so observers in that match can be rebuilt
+ Guid previousMatch = currentMatch;
+
+ // Set this to the new match this object just entered ...
+ currentMatch = value;
+ // ... and copy the string for the inspector because Unity can't show Guid directly
+ currentMatchDebug = currentMatch.ToString();
+
+ if (previousMatch != Guid.Empty)
+ {
+ // Remove this object from the hashset of the match it just left
+ matchPlayers[previousMatch].Remove(netIdentity);
+
+ // RebuildObservers of all NetworkIdentity's in the match this object just left
+ RebuildMatchObservers(previousMatch);
+ }
+
+ if (currentMatch != Guid.Empty)
+ {
+ // Make sure this new match is in the dictionary
+ if (!matchPlayers.ContainsKey(currentMatch))
+ matchPlayers.Add(currentMatch, new HashSet());
+
+ // Add this object to the hashset of the new match
+ matchPlayers[currentMatch].Add(netIdentity);
+
+ // RebuildObservers of all NetworkIdentity's in the match this object just entered
+ RebuildMatchObservers(currentMatch);
+ }
+ else
+ {
+ // Not in any match now...RebuildObservers will clear and add self
+ netIdentity.RebuildObservers(false);
+ }
+ }
+ }
+
+ public override void OnStartServer()
+ {
+ if (currentMatch == Guid.Empty) return;
+
+ if (!matchPlayers.ContainsKey(currentMatch))
+ matchPlayers.Add(currentMatch, new HashSet());
+
+ matchPlayers[currentMatch].Add(netIdentity);
+
+ // No need to rebuild anything here.
+ // identity.RebuildObservers is called right after this from NetworkServer.SpawnObject
+ }
+
+ void RebuildMatchObservers(Guid specificMatch)
+ {
+ foreach (NetworkIdentity networkIdentity in matchPlayers[specificMatch])
+ if (networkIdentity != null)
+ networkIdentity.RebuildObservers(false);
+ }
+
+ #region Observers
+
+ ///
+ /// Callback used by the visibility system to determine if an observer (player) can see this object.
+ /// If this function returns true, the network connection will be added as an observer.
+ ///
+ /// Network connection of a player.
+ /// True if the player can see this object.
+ public override bool OnCheckObserver(NetworkConnection conn)
+ {
+ // Not Visible if not in a match
+ if (matchId == Guid.Empty)
+ return false;
+
+ NetworkMatchChecker networkMatchChecker = conn.identity.GetComponent();
+
+ if (networkMatchChecker == null)
+ return false;
+
+ return networkMatchChecker.matchId == matchId;
+ }
+
+ ///
+ /// Callback used by the visibility system to (re)construct the set of observers that can see this object.
+ /// Implementations of this callback should add network connections of players that can see this object to the observers set.
+ ///
+ /// The new set of observers for this object.
+ /// True if the set of observers is being built for the first time.
+ public override void OnRebuildObservers(HashSet observers, bool initialize)
+ {
+ if (currentMatch == Guid.Empty) return;
+
+ foreach (NetworkIdentity networkIdentity in matchPlayers[currentMatch])
+ if (networkIdentity != null && networkIdentity.connectionToClient != null)
+ observers.Add(networkIdentity.connectionToClient);
+ }
+
+ #endregion
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkMatchChecker.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkMatchChecker.cs.meta
new file mode 100644
index 0000000..7c7d6cf
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkMatchChecker.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1020a74962faada4b807ac5dc053a4cf
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkPingDisplay.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkPingDisplay.cs
new file mode 100644
index 0000000..46863bf
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkPingDisplay.cs
@@ -0,0 +1,41 @@
+using UnityEngine;
+
+namespace Mirror
+{
+ ///
+ /// Component that will display the clients ping in milliseconds
+ ///
+ [DisallowMultipleComponent]
+ [AddComponentMenu("Network/NetworkPingDisplay")]
+ [HelpURL("https://mirror-networking.com/docs/Components/NetworkPingDisplay.html")]
+ public class NetworkPingDisplay : MonoBehaviour
+ {
+ [SerializeField] bool showPing = true;
+ [SerializeField] Vector2 position = new Vector2(200, 0);
+ [SerializeField] int fontSize = 24;
+ [SerializeField] Color textColor = new Color32(255, 255, 255, 80);
+
+ GUIStyle style;
+
+ void Awake()
+ {
+ style = new GUIStyle();
+ style.alignment = TextAnchor.UpperLeft;
+ style.fontSize = fontSize;
+ style.normal.textColor = textColor;
+ }
+
+ void OnGUI()
+ {
+ if (!showPing) { return; }
+
+ string text = string.Format("{0}ms", (int)(NetworkTime.rtt * 1000));
+
+ int width = Screen.width;
+ int height = Screen.height;
+ Rect rect = new Rect(position.x, position.y, width - 200, height * 2 / 100);
+
+ GUI.Label(rect, text, style);
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkPingDisplay.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkPingDisplay.cs.meta
new file mode 100644
index 0000000..221a745
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkPingDisplay.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bc654f29862fc2643b948f772ebb9e68
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkProximityChecker.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkProximityChecker.cs
index 88456ea..719ae07 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkProximityChecker.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkProximityChecker.cs
@@ -10,17 +10,8 @@ namespace Mirror
[AddComponentMenu("Network/NetworkProximityChecker")]
[RequireComponent(typeof(NetworkIdentity))]
[HelpURL("https://mirror-networking.com/docs/Components/NetworkProximityChecker.html")]
- public class NetworkProximityChecker : NetworkBehaviour
+ public class NetworkProximityChecker : NetworkVisibility
{
- ///
- /// Enumeration of methods to use to check proximity.
- ///
- public enum CheckMethod
- {
- Physics3D,
- Physics2D
- }
-
///
/// The maximim range that objects will be visible at.
///
@@ -33,14 +24,6 @@ public enum CheckMethod
[Tooltip("How often (in seconds) that this object should update the list of observers that can see it.")]
public float visUpdateInterval = 1;
- ///
- /// Which method to use for checking proximity of players.
- /// Physics3D uses 3D physics to determine proximity.
- /// Physics2D uses 2D physics to determine proximity.
- ///
- [Tooltip("Which method to use for checking proximity of players.\n\nPhysics3D uses 3D physics to determine proximity.\nPhysics2D uses 2D physics to determine proximity.")]
- public CheckMethod checkMethod = CheckMethod.Physics3D;
-
///
/// Flag to force this object to be hidden for players.
/// If this object is a player object, it will not be hidden for that player.
@@ -48,123 +31,67 @@ public enum CheckMethod
[Tooltip("Enable to force this object to be hidden from players.")]
public bool forceHidden;
- // Layers are used anyway, might as well expose them to the user.
- ///
- /// Select only the Player's layer to avoid unnecessary SphereCasts against the Terrain, etc.
- /// ~0 means 'Everything'.
- ///
- [Tooltip("Select only the Player's layer to avoid unnecessary SphereCasts against the Terrain, etc.")]
- public LayerMask castLayers = ~0;
-
- float lastUpdateTime;
- // OverlapSphereNonAlloc array to avoid allocations.
- // -> static so we don't create one per component
- // -> this is worth it because proximity checking happens for just about
- // every entity on the server!
- // -> should be big enough to work in just about all cases
- static Collider[] hitsBuffer3D = new Collider[10000];
- static Collider2D[] hitsBuffer2D = new Collider2D[10000];
-
- void Update()
+ public override void OnStartServer()
{
- if (!NetworkServer.active)
- return;
+ InvokeRepeating(nameof(RebuildObservers), 0, visUpdateInterval);
+ }
+ public override void OnStopServer()
+ {
+ CancelInvoke(nameof(RebuildObservers));
+ }
- if (Time.time - lastUpdateTime > visUpdateInterval)
- {
- netIdentity.RebuildObservers(false);
- lastUpdateTime = Time.time;
- }
+ void RebuildObservers()
+ {
+ netIdentity.RebuildObservers(false);
}
///
- /// Called when a new player enters
+ /// Callback used by the visibility system to determine if an observer (player) can see this object.
+ /// If this function returns true, the network connection will be added as an observer.
///
- ///
- ///
- public override bool OnCheckObserver(NetworkConnection newObserver)
+ /// Network connection of a player.
+ /// True if the player can see this object.
+ public override bool OnCheckObserver(NetworkConnection conn)
{
if (forceHidden)
return false;
- return Vector3.Distance(newObserver.identity.transform.position, transform.position) < visRange;
+ return Vector3.Distance(conn.identity.transform.position, transform.position) < visRange;
}
///
- /// Called when a new player enters, and when scene changes occur
+ /// Callback used by the visibility system to (re)construct the set of observers that can see this object.
+ /// Implementations of this callback should add network connections of players that can see this object to the observers set.
///
- /// List of players to be updated. Modify this set with all the players that can see this object
- /// True if this is the first time the method is called for this object
- /// True if this component calculated the list of observers
- public override bool OnRebuildObservers(HashSet observers, bool initial)
+ /// The new set of observers for this object.
+ /// True if the set of observers is being built for the first time.
+ public override void OnRebuildObservers(HashSet observers, bool initialize)
{
// if force hidden then return without adding any observers.
if (forceHidden)
- // always return true when overwriting OnRebuildObservers so that
- // Mirror knows not to use the built in rebuild method.
- return true;
+ return;
- // find players within range
- switch (checkMethod)
+ // 'transform.' calls GetComponent, only do it once
+ Vector3 position = transform.position;
+
+ // brute force distance check
+ // -> only player connections can be observers, so it's enough if we
+ // go through all connections instead of all spawned identities.
+ // -> compared to UNET's sphere cast checking, this one is orders of
+ // magnitude faster. if we have 10k monsters and run a sphere
+ // cast 10k times, we will see a noticeable lag even with physics
+ // layers. but checking to every connection is fast.
+ foreach (NetworkConnectionToClient conn in NetworkServer.connections.Values)
{
- case CheckMethod.Physics3D:
- {
- // cast without allocating GC for maximum performance
- int hitCount = Physics.OverlapSphereNonAlloc(transform.position, visRange, hitsBuffer3D, castLayers);
- if (hitCount == hitsBuffer3D.Length) Debug.LogWarning("NetworkProximityChecker's OverlapSphere test for " + name + " has filled the whole buffer(" + hitsBuffer3D.Length + "). Some results might have been omitted. Consider increasing buffer size.");
-
- for (int i = 0; i < hitCount; i++)
- {
- Collider hit = hitsBuffer3D[i];
- // collider might be on pelvis, often the NetworkIdentity is in a parent
- // (looks in the object itself and then parents)
- NetworkIdentity identity = hit.GetComponentInParent();
- // (if an object has a connectionToClient, it is a player)
- if (identity != null && identity.connectionToClient != null)
- {
- observers.Add(identity.connectionToClient);
- }
- }
- break;
- }
-
- case CheckMethod.Physics2D:
+ if (conn != null && conn.identity != null)
+ {
+ // check distance
+ if (Vector3.Distance(conn.identity.transform.position, position) < visRange)
{
- // cast without allocating GC for maximum performance
- int hitCount = Physics2D.OverlapCircleNonAlloc(transform.position, visRange, hitsBuffer2D, castLayers);
- if (hitCount == hitsBuffer2D.Length) Debug.LogWarning("NetworkProximityChecker's OverlapCircle test for " + name + " has filled the whole buffer(" + hitsBuffer2D.Length + "). Some results might have been omitted. Consider increasing buffer size.");
-
- for (int i = 0; i < hitCount; i++)
- {
- Collider2D hit = hitsBuffer2D[i];
- // collider might be on pelvis, often the NetworkIdentity is in a parent
- // (looks in the object itself and then parents)
- NetworkIdentity identity = hit.GetComponentInParent();
- // (if an object has a connectionToClient, it is a player)
- if (identity != null && identity.connectionToClient != null)
- {
- observers.Add(identity.connectionToClient);
- }
- }
- break;
+ observers.Add(conn);
}
- }
-
- // always return true when overwriting OnRebuildObservers so that
- // Mirror knows not to use the built in rebuild method.
- return true;
- }
-
- ///
- /// Called when hiding and showing objects on the host
- ///
- ///
- public override void OnSetLocalVisibility(bool visible)
- {
- foreach (Renderer rend in GetComponentsInChildren())
- {
- rend.enabled = visible;
+ }
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkProximityChecker.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkProximityChecker.cs.meta
index 79e50e8..c5aa112 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkProximityChecker.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkProximityChecker.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomManager.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomManager.cs
index 69627a7..7f29f98 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomManager.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomManager.cs
@@ -1,4 +1,6 @@
+using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
@@ -18,6 +20,8 @@ namespace Mirror
[HelpURL("https://mirror-networking.com/docs/Components/NetworkRoomManager.html")]
public class NetworkRoomManager : NetworkManager
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkRoomManager));
+
public struct PendingPlayer
{
public NetworkConnection conn;
@@ -28,15 +32,18 @@ public struct PendingPlayer
[FormerlySerializedAs("m_ShowRoomGUI")]
[SerializeField]
+ [Tooltip("This flag controls whether the default UI is shown for the room")]
internal bool showRoomGUI = true;
[FormerlySerializedAs("m_MinPlayers")]
[SerializeField]
- int minPlayers = 1;
+ [Tooltip("Minimum number of players to auto-start the game")]
+ protected int minPlayers = 1;
[FormerlySerializedAs("m_RoomPlayerPrefab")]
[SerializeField]
- NetworkRoomPlayer roomPlayerPrefab;
+ [Tooltip("Prefab to use for the Room Player")]
+ protected NetworkRoomPlayer roomPlayerPrefab;
///
/// The scene to use for the room. This is similar to the offlineScene of the NetworkManager.
@@ -56,16 +63,45 @@ public struct PendingPlayer
[FormerlySerializedAs("m_PendingPlayers")]
public List pendingPlayers = new List();
+ [Header("Diagnostics")]
+
+ ///
+ /// True when all players have submitted a Ready message
+ ///
+ [Tooltip("Diagnostic flag indicating all players are ready to play")]
+ [FormerlySerializedAs("allPlayersReady")]
+ [SerializeField] bool _allPlayersReady;
+
///
/// These slots track players that enter the room.
/// The slotId on players is global to the game - across all players.
///
+ [Tooltip("List of Room Player objects")]
public List roomSlots = new List();
- ///
- /// True when all players have submitted a Ready message
- ///
- public bool allPlayersReady;
+ public bool allPlayersReady
+ {
+ get => _allPlayersReady;
+ set
+ {
+ bool wasReady = _allPlayersReady;
+ bool nowReady = value;
+
+ if (wasReady != nowReady)
+ {
+ _allPlayersReady = value;
+
+ if (nowReady)
+ {
+ OnRoomServerPlayersReady();
+ }
+ else
+ {
+ OnRoomServerPlayersNotReady();
+ }
+ }
+ }
+ }
public override void OnValidate()
{
@@ -84,7 +120,7 @@ public override void OnValidate()
if (identity == null)
{
roomPlayerPrefab = null;
- Debug.LogError("RoomPlayer prefab must have a NetworkIdentity component.");
+ logger.LogError("RoomPlayer prefab must have a NetworkIdentity component.");
}
}
@@ -113,12 +149,13 @@ internal void ReadyStatusChanged()
}
///
- ///
+ /// Called on the server when a client is ready.
+ /// The default implementation of this function calls NetworkServer.SetClientReady() to continue the network setup process.
///
- /// Connection of the client
+ /// Connection from client.
public override void OnServerReady(NetworkConnection conn)
{
- if (LogFilter.Debug) Debug.Log("NetworkRoomManager OnServerReady");
+ logger.Log("NetworkRoomManager OnServerReady");
base.OnServerReady(conn);
if (conn != null && conn.identity != null)
@@ -133,9 +170,9 @@ public override void OnServerReady(NetworkConnection conn)
void SceneLoadedForPlayer(NetworkConnection conn, GameObject roomPlayer)
{
- if (LogFilter.Debug) Debug.LogFormat("NetworkRoom SceneLoadedForPlayer scene: {0} {1}", SceneManager.GetActiveScene().name, conn);
+ if (logger.LogEnabled()) logger.LogFormat(LogType.Log, "NetworkRoom SceneLoadedForPlayer scene: {0} {1}", SceneManager.GetActiveScene().path, conn);
- if (SceneManager.GetActiveScene().name == RoomScene)
+ if (IsSceneActive(RoomScene))
{
// cant be ready in room, add to ready list
PendingPlayer pending;
@@ -145,7 +182,7 @@ void SceneLoadedForPlayer(NetworkConnection conn, GameObject roomPlayer)
return;
}
- GameObject gamePlayer = OnRoomServerCreateGamePlayer(conn);
+ GameObject gamePlayer = OnRoomServerCreateGamePlayer(conn, roomPlayer);
if (gamePlayer == null)
{
// get start position from base class
@@ -153,33 +190,35 @@ void SceneLoadedForPlayer(NetworkConnection conn, GameObject roomPlayer)
gamePlayer = startPos != null
? Instantiate(playerPrefab, startPos.position, startPos.rotation)
: Instantiate(playerPrefab, Vector3.zero, Quaternion.identity);
- gamePlayer.name = playerPrefab.name;
}
- if (!OnRoomServerSceneLoadedForPlayer(roomPlayer, gamePlayer))
+ if (!OnRoomServerSceneLoadedForPlayer(conn, roomPlayer, gamePlayer))
return;
// replace room player with game player
- NetworkServer.ReplacePlayerForConnection(conn, gamePlayer);
+ NetworkServer.ReplacePlayerForConnection(conn, gamePlayer, true);
}
///
/// CheckReadyToBegin checks all of the players in the room to see if their readyToBegin flag is set.
- /// If all of the players are ready, then the server switches from the RoomScene to the PlayScene - essentially starting the game. This is called automatically in response to NetworkRoomPlayer.SendReadyToBeginMessage().
+ /// If all of the players are ready, then the server switches from the RoomScene to the PlayScene, essentially starting the game. This is called automatically in response to NetworkRoomPlayer.CmdChangeReadyState.
///
public void CheckReadyToBegin()
{
- if (SceneManager.GetActiveScene().name != RoomScene) return;
+ if (!IsSceneActive(RoomScene))
+ return;
- if (minPlayers > 0 && NetworkServer.connections.Count(conn => conn.Value != null && conn.Value.identity.gameObject.GetComponent().readyToBegin) < minPlayers)
+ int numberOfReadyPlayers = NetworkServer.connections.Count(conn => conn.Value != null && conn.Value.identity.gameObject.GetComponent().readyToBegin);
+ bool enoughReadyPlayers = minPlayers <= 0 || numberOfReadyPlayers >= minPlayers;
+ if (enoughReadyPlayers)
+ {
+ pendingPlayers.Clear();
+ allPlayersReady = true;
+ }
+ else
{
allPlayersReady = false;
- return;
}
-
- pendingPlayers.Clear();
- allPlayersReady = true;
- OnRoomServerPlayersReady();
}
void CallOnClientEnterRoom()
@@ -205,9 +244,10 @@ void CallOnClientExitRoom()
#region server handlers
///
- ///
+ /// Called on the server when a new client connects.
+ /// Unity calls this on the Server when a Client connects to the Server. Use an override to tell the NetworkManager what to do when a client connects to the server.
///
- /// Connection of the client
+ /// Connection from client.
public override void OnServerConnect(NetworkConnection conn)
{
if (numPlayers >= maxConnections)
@@ -217,7 +257,7 @@ public override void OnServerConnect(NetworkConnection conn)
}
// cannot join game in progress
- if (SceneManager.GetActiveScene().name != RoomScene)
+ if (!IsSceneActive(RoomScene))
{
conn.Disconnect();
return;
@@ -228,17 +268,25 @@ public override void OnServerConnect(NetworkConnection conn)
}
///
- ///
+ /// Called on the server when a client disconnects.
+ /// This is called on the Server when a Client disconnects from the Server. Use an override to decide what should happen when a disconnection is detected.
///
- /// Connection of the client
+ /// Connection from client.
public override void OnServerDisconnect(NetworkConnection conn)
{
if (conn.identity != null)
{
- NetworkRoomPlayer player = conn.identity.GetComponent();
+ NetworkRoomPlayer roomPlayer = conn.identity.GetComponent();
- if (player != null)
- roomSlots.Remove(player);
+ if (roomPlayer != null)
+ roomSlots.Remove(roomPlayer);
+
+ foreach (NetworkIdentity clientOwnedObject in conn.clientOwnedObjects)
+ {
+ roomPlayer = clientOwnedObject.GetComponent();
+ if (roomPlayer != null)
+ roomSlots.Remove(roomPlayer);
+ }
}
allPlayersReady = false;
@@ -249,42 +297,40 @@ public override void OnServerDisconnect(NetworkConnection conn)
player.GetComponent().readyToBegin = false;
}
- if (SceneManager.GetActiveScene().name == RoomScene)
+ if (IsSceneActive(RoomScene))
RecalculateRoomPlayerIndices();
- base.OnServerDisconnect(conn);
OnRoomServerDisconnect(conn);
+ base.OnServerDisconnect(conn);
}
///
- ///
+ /// Called on the server when a client adds a new player with ClientScene.AddPlayer.
+ /// The default implementation for this function creates a new player object from the playerPrefab.
///
- /// Connection of the client
- ///
+ /// Connection from client.
public override void OnServerAddPlayer(NetworkConnection conn)
{
- if (SceneManager.GetActiveScene().name != RoomScene) return;
-
- if (roomSlots.Count == maxConnections) return;
-
- allPlayersReady = false;
-
- if (LogFilter.Debug) Debug.LogFormat("NetworkRoomManager.OnServerAddPlayer playerPrefab:{0}", roomPlayerPrefab.name);
-
- GameObject newRoomGameObject = OnRoomServerCreateRoomPlayer(conn);
- if (newRoomGameObject == null)
- newRoomGameObject = (GameObject)Instantiate(roomPlayerPrefab.gameObject, Vector3.zero, Quaternion.identity);
+ if (IsSceneActive(RoomScene))
+ {
+ if (roomSlots.Count == maxConnections)
+ return;
- NetworkRoomPlayer newRoomPlayer = newRoomGameObject.GetComponent();
+ allPlayersReady = false;
- roomSlots.Add(newRoomPlayer);
+ if (logger.LogEnabled()) logger.LogFormat(LogType.Log, "NetworkRoomManager.OnServerAddPlayer playerPrefab:{0}", roomPlayerPrefab.name);
- RecalculateRoomPlayerIndices();
+ GameObject newRoomGameObject = OnRoomServerCreateRoomPlayer(conn);
+ if (newRoomGameObject == null)
+ newRoomGameObject = Instantiate(roomPlayerPrefab.gameObject, Vector3.zero, Quaternion.identity);
- NetworkServer.AddPlayerForConnection(conn, newRoomGameObject);
+ NetworkServer.AddPlayerForConnection(conn, newRoomGameObject);
+ }
+ else
+ OnRoomServerAddPlayer(conn);
}
- void RecalculateRoomPlayerIndices()
+ public void RecalculateRoomPlayerIndices()
{
if (roomSlots.Count > 0)
{
@@ -296,23 +342,22 @@ void RecalculateRoomPlayerIndices()
}
///
- ///
+ /// This causes the server to switch scenes and sets the networkSceneName.
+ /// Clients that connect to this server will automatically switch to this scene. This is called autmatically if onlineScene or offlineScene are set, but it can be called from user code to switch scenes again while the game is in progress. This automatically sets clients to be not-ready. The clients must call NetworkClient.Ready() again to participate in the new scene.
///
- ///
- public override void ServerChangeScene(string sceneName)
+ ///
+ public override void ServerChangeScene(string newSceneName)
{
- if (sceneName == RoomScene)
+ if (newSceneName == RoomScene)
{
foreach (NetworkRoomPlayer roomPlayer in roomSlots)
{
- if (roomPlayer == null) continue;
+ if (roomPlayer == null)
+ continue;
// find the game-player object for this connection, and destroy it
NetworkIdentity identity = roomPlayer.GetComponent();
- NetworkIdentity playerController = identity.connectionToClient.identity;
- NetworkServer.Destroy(playerController.gameObject);
-
if (NetworkServer.active)
{
// re-add the room object
@@ -320,15 +365,17 @@ public override void ServerChangeScene(string sceneName)
NetworkServer.ReplacePlayerForConnection(identity.connectionToClient, roomPlayer.gameObject);
}
}
+
+ allPlayersReady = false;
}
- base.ServerChangeScene(sceneName);
+ base.ServerChangeScene(newSceneName);
}
///
- ///
+ /// Called on the server when a scene is completed loaded, when the scene load was initiated by the server with ServerChangeScene().
///
- ///
+ /// The name of the new scene.
public override void OnServerSceneChanged(string sceneName)
{
if (sceneName != RoomScene)
@@ -344,19 +391,20 @@ public override void OnServerSceneChanged(string sceneName)
}
///
- ///
+ /// This is invoked when a server is started - including when a host is started.
+ /// StartServer has multiple signatures, but they all cause this hook to be called.
///
public override void OnStartServer()
{
if (string.IsNullOrEmpty(RoomScene))
{
- Debug.LogError("NetworkRoomManager RoomScene is empty. Set the RoomScene in the inspector for the NetworkRoomMangaer");
+ logger.LogError("NetworkRoomManager RoomScene is empty. Set the RoomScene in the inspector for the NetworkRoomMangaer");
return;
}
if (string.IsNullOrEmpty(GameplayScene))
{
- Debug.LogError("NetworkRoomManager PlayScene is empty. Set the PlayScene in the inspector for the NetworkRoomMangaer");
+ logger.LogError("NetworkRoomManager PlayScene is empty. Set the PlayScene in the inspector for the NetworkRoomMangaer");
return;
}
@@ -364,7 +412,8 @@ public override void OnStartServer()
}
///
- ///
+ /// This is invoked when a host is started.
+ /// StartHost has multiple signatures, but they all cause this hook to be called.
///
public override void OnStartHost()
{
@@ -372,16 +421,16 @@ public override void OnStartHost()
}
///
- ///
+ /// This is called when a server is stopped - including when a host is stopped.
///
public override void OnStopServer()
{
roomSlots.Clear();
- base.OnStopServer();
+ OnRoomStopServer();
}
///
- ///
+ /// This is called when a host is stopped.
///
public override void OnStopHost()
{
@@ -393,27 +442,26 @@ public override void OnStopHost()
#region client handlers
///
- ///
+ /// This is invoked when the client is started.
///
public override void OnStartClient()
{
if (roomPlayerPrefab == null || roomPlayerPrefab.gameObject == null)
- Debug.LogError("NetworkRoomManager no RoomPlayer prefab is registered. Please add a RoomPlayer prefab.");
+ logger.LogError("NetworkRoomManager no RoomPlayer prefab is registered. Please add a RoomPlayer prefab.");
else
ClientScene.RegisterPrefab(roomPlayerPrefab.gameObject);
if (playerPrefab == null)
- Debug.LogError("NetworkRoomManager no GamePlayer prefab is registered. Please add a GamePlayer prefab.");
- else
- ClientScene.RegisterPrefab(playerPrefab);
+ logger.LogError("NetworkRoomManager no GamePlayer prefab is registered. Please add a GamePlayer prefab.");
OnRoomStartClient();
}
///
- ///
+ /// Called on the client when connected to a server.
+ /// The default implementation of this function sets the client as ready and adds a player. Override the function to dictate what happens when the client connects.
///
- /// Connection of the client
+ /// Connection to the server.
public override void OnClientConnect(NetworkConnection conn)
{
OnRoomClientConnect(conn);
@@ -422,9 +470,10 @@ public override void OnClientConnect(NetworkConnection conn)
}
///
- ///
+ /// Called on clients when disconnected from a server.
+ /// This is called on the client when it disconnects from the server. Override this function to decide what happens when the client disconnects.
///
- /// Connection of the client
+ /// Connection to the server.
public override void OnClientDisconnect(NetworkConnection conn)
{
OnRoomClientDisconnect(conn);
@@ -432,28 +481,23 @@ public override void OnClientDisconnect(NetworkConnection conn)
}
///
- ///
+ /// This is called when a client is stopped.
///
public override void OnStopClient()
{
OnRoomStopClient();
CallOnClientExitRoom();
-
- if (!string.IsNullOrEmpty(offlineScene))
- {
- // Move the RoomManager from the virtual DontDestroyOnLoad scene to the Game scene.
- // This let's it be destroyed when client changes to the Offline scene.
- SceneManager.MoveGameObjectToScene(gameObject, SceneManager.GetActiveScene());
- }
+ roomSlots.Clear();
}
///
- ///
+ /// Called on clients when a scene has completed loaded, when the scene load was initiated by the server.
+ /// Scene changes can cause player objects to be destroyed. The default implementation of OnClientSceneChanged in the NetworkManager is to add a player object for the connection if no player object exists.
///
/// Connection of the client
public override void OnClientSceneChanged(NetworkConnection conn)
{
- if (SceneManager.GetActiveScene().name == RoomScene)
+ if (IsSceneActive(RoomScene))
{
if (NetworkClient.isConnected)
CallOnClientEnterRoom();
@@ -484,6 +528,11 @@ public virtual void OnRoomStopHost() { }
///
public virtual void OnRoomStartServer() { }
+ ///
+ /// This is called on the server when the server is started - including when a host is stopped.
+ ///
+ public virtual void OnRoomStopServer() { }
+
///
/// This is called on the server when a new client connects to the server.
///
@@ -513,26 +562,61 @@ public virtual GameObject OnRoomServerCreateRoomPlayer(NetworkConnection conn)
return null;
}
+ // Deprecated 12/17/2019
+ ///
+ /// Obsolete: Use OnRoomServerCreateGamePlayer(NetworkConnection, GameObject) instead.
+ ///
+ /// The connection the player object is for.
+ /// A new GamePlayer object.
+ [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use OnRoomServerCreateGamePlayer(NetworkConnection conn, GameObject roomPlayer) instead", true)]
+ public virtual GameObject OnRoomServerCreateGamePlayer(NetworkConnection conn)
+ {
+ return null;
+ }
+
///
/// This allows customization of the creation of the GamePlayer object on the server.
/// By default the gamePlayerPrefab is used to create the game-player, but this function allows that behaviour to be customized. The object returned from the function will be used to replace the room-player on the connection.
///
/// The connection the player object is for.
+ /// The room player object for this connection.
/// A new GamePlayer object.
- public virtual GameObject OnRoomServerCreateGamePlayer(NetworkConnection conn)
+ public virtual GameObject OnRoomServerCreateGamePlayer(NetworkConnection conn, GameObject roomPlayer)
{
return null;
}
+ ///
+ /// This allows customization of the creation of the GamePlayer object on the server.
+ /// This is only called for subsequent GamePlay scenes after the first one.
+ /// See OnRoomServerCreateGamePlayer(NetworkConnection, GameObject) to customize the player object for the initial GamePlay scene.
+ ///
+ /// The connection the player object is for.
+ public virtual void OnRoomServerAddPlayer(NetworkConnection conn)
+ {
+ base.OnServerAddPlayer(conn);
+ }
+
+ // Deprecated 02/22/2020
+ ///
+ /// Obsolete: Use OnRoomServerSceneLoadedForPlayer(NetworkConnection, GameObject, GameObject) instead.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use OnRoomServerSceneLoadedForPlayer(NetworkConnection conn, GameObject roomPlayer, GameObject gamePlayer) instead")]
+ public virtual bool OnRoomServerSceneLoadedForPlayer(GameObject roomPlayer, GameObject gamePlayer)
+ {
+ return true;
+ }
+
// for users to apply settings from their room player object to their in-game player object
///
/// This is called on the server when it is told that a client has finished switching from the room scene to a game player scene.
/// When switching from the room, the room-player is replaced with a game-player object. This callback function gives an opportunity to apply state from the room-player to the game-player object.
///
+ /// The connection of the player
/// The room player object.
/// The game player object.
/// False to not allow this player to replace the room player.
- public virtual bool OnRoomServerSceneLoadedForPlayer(GameObject roomPlayer, GameObject gamePlayer)
+ public virtual bool OnRoomServerSceneLoadedForPlayer(NetworkConnection conn, GameObject roomPlayer, GameObject gamePlayer)
{
return true;
}
@@ -547,6 +631,12 @@ public virtual void OnRoomServerPlayersReady()
ServerChangeScene(GameplayScene);
}
+ ///
+ /// This is called on the server when CheckReadyToBegin finds that players are not ready
+ /// May be called multiple times while not ready players are joining
+ ///
+ public virtual void OnRoomServerPlayersNotReady() { }
+
#endregion
#region room client virtuals
@@ -608,10 +698,16 @@ public virtual void OnGUI()
if (!showRoomGUI)
return;
- if (SceneManager.GetActiveScene().name != RoomScene)
- return;
+ if (NetworkServer.active && IsSceneActive(GameplayScene))
+ {
+ GUILayout.BeginArea(new Rect(Screen.width - 150f, 10f, 140f, 30f));
+ if (GUILayout.Button("Return to Room"))
+ ServerChangeScene(RoomScene);
+ GUILayout.EndArea();
+ }
- GUI.Box(new Rect(10f, 180f, 520f, 150f), "PLAYERS");
+ if (IsSceneActive(RoomScene))
+ GUI.Box(new Rect(10f, 180f, 520f, 150f), "PLAYERS");
}
#endregion
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomManager.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomManager.cs.meta
index 35b6436..76e7d42 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomManager.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomManager.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomPlayer.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomPlayer.cs
index e0dfe4f..5f97060 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomPlayer.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomPlayer.cs
@@ -1,5 +1,6 @@
+using System;
+using System.ComponentModel;
using UnityEngine;
-using UnityEngine.SceneManagement;
namespace Mirror
{
@@ -12,23 +13,31 @@ namespace Mirror
[HelpURL("https://mirror-networking.com/docs/Components/NetworkRoomPlayer.html")]
public class NetworkRoomPlayer : NetworkBehaviour
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkRoomPlayer));
+
///
/// This flag controls whether the default UI is shown for the room player.
/// As this UI is rendered using the old GUI system, it is only recommended for testing purposes.
///
+ [Tooltip("This flag controls whether the default UI is shown for the room player")]
public bool showRoomGUI = true;
+ [Header("Diagnostics")]
+
///
- /// This is a flag that control whether this player is ready for the game to begin.
- /// When all players are ready to begin, the game will start. This should not be set directly, the SendReadyToBeginMessage function should be called on the client to set it on the server.
+ /// Diagnostic flag indicating whether this player is ready for the game to begin.
+ /// Invoke CmdChangeReadyState method on the client to set this flag.
+ /// When all players are ready to begin, the game will start. This should not be set directly, CmdChangeReadyState should be called on the client to set it on the server.
///
+ [Tooltip("Diagnostic flag indicating whether this player is ready for the game to begin")]
[SyncVar(hook = nameof(ReadyStateChanged))]
public bool readyToBegin;
///
- /// Current index of the player, e.g. Player1, Player2, etc.
+ /// Diagnostic index of the player, e.g. Player1, Player2, etc.
///
- [SyncVar]
+ [Tooltip("Diagnostic index of the player, e.g. Player1, Player2, etc.")]
+ [SyncVar(hook = nameof(IndexChanged))]
public int index;
#region Unity Callbacks
@@ -41,15 +50,28 @@ public void Start()
if (NetworkManager.singleton is NetworkRoomManager room)
{
// NetworkRoomPlayer object must be set to DontDestroyOnLoad along with NetworkRoomManager
- // in server and all clients, otherwise it will be respawned in the game scene which would
+ // in server and all clients, otherwise it will be respawned in the game scene which would
// have undesireable effects.
if (room.dontDestroyOnLoad)
DontDestroyOnLoad(gameObject);
- OnClientEnterRoom();
+ room.roomSlots.Add(this);
+ room.RecalculateRoomPlayerIndices();
+
+ if (NetworkClient.active)
+ OnClientEnterRoom();
}
else
- Debug.LogError("RoomPlayer could not find a NetworkRoomManager. The RoomPlayer requires a NetworkRoomManager object to function. Make sure that there is one in the scene.");
+ logger.LogError("RoomPlayer could not find a NetworkRoomManager. The RoomPlayer requires a NetworkRoomManager object to function. Make sure that there is one in the scene.");
+ }
+
+ public virtual void OnDisable()
+ {
+ if (NetworkClient.active && NetworkManager.singleton is NetworkRoomManager room)
+ {
+ room.roomSlots.Remove(this);
+ room.RecalculateRoomPlayerIndices();
+ }
}
#endregion
@@ -71,9 +93,23 @@ public void CmdChangeReadyState(bool readyState)
#region SyncVar Hooks
- void ReadyStateChanged(bool newReadyState)
+ ///
+ /// This is a hook that is invoked on clients when the index changes.
+ ///
+ /// The old index value
+ /// The new index value
+ public virtual void IndexChanged(int oldIndex, int newIndex) { }
+
+ ///
+ /// This is a hook that is invoked on clients when a RoomPlayer switches between ready or not ready.
+ /// This function is called when the a client player calls CmdChangeReadyState.
+ ///
+ /// New Ready State
+ public virtual void ReadyStateChanged(bool _, bool newReadyState)
{
+#pragma warning disable CS0618 // Type or member is obsolete
OnClientReady(newReadyState);
+#pragma warning restore CS0618 // Type or member is obsolete
}
#endregion
@@ -81,21 +117,21 @@ void ReadyStateChanged(bool newReadyState)
#region Room Client Virtuals
///
- /// This is a hook that is invoked on all player objects when entering the room.
+ /// This is a hook that is invoked on clients for all room player objects when entering the room.
/// Note: isLocalPlayer is not guaranteed to be set until OnStartLocalPlayer is called.
///
public virtual void OnClientEnterRoom() { }
///
- /// This is a hook that is invoked on all player objects when exiting the room.
+ /// This is a hook that is invoked on clients for all room player objects when exiting the room.
///
public virtual void OnClientExitRoom() { }
+ // Deprecated 05/18/2020
///
- /// This is a hook that is invoked on clients when a RoomPlayer switches between ready or not ready.
- /// This function is called when the a client player calls SendReadyToBeginMessage() or SendNotReadyToBeginMessage().
+ /// Obsolete: Override ReadyStateChanged(bool, bool) instead.
///
- /// Whether the player is ready or not.
+ [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Override ReadyStateChanged(bool, bool) instead")]
public virtual void OnClientReady(bool readyState) { }
#endregion
@@ -116,45 +152,54 @@ public virtual void OnGUI()
if (!room.showRoomGUI)
return;
- if (SceneManager.GetActiveScene().name != room.RoomScene)
+ if (!NetworkManager.IsSceneActive(room.RoomScene))
return;
- GUILayout.BeginArea(new Rect(20f + (index * 100), 200f, 90f, 130f));
+ DrawPlayerReadyState();
+ DrawPlayerReadyButton();
+ }
+ }
- GUILayout.Label($"Player [{index + 1}]");
+ void DrawPlayerReadyState()
+ {
+ GUILayout.BeginArea(new Rect(20f + (index * 100), 200f, 90f, 130f));
+
+ GUILayout.Label($"Player [{index + 1}]");
+
+ if (readyToBegin)
+ GUILayout.Label("Ready");
+ else
+ GUILayout.Label("Not Ready");
+
+ if (((isServer && index > 0) || isServerOnly) && GUILayout.Button("REMOVE"))
+ {
+ // This button only shows on the Host for all players other than the Host
+ // Host and Players can't remove themselves (stop the client instead)
+ // Host can kick a Player this way.
+ GetComponent().connectionToClient.Disconnect();
+ }
+
+ GUILayout.EndArea();
+ }
+
+ void DrawPlayerReadyButton()
+ {
+ if (NetworkClient.active && isLocalPlayer)
+ {
+ GUILayout.BeginArea(new Rect(20f, 300f, 120f, 20f));
if (readyToBegin)
- GUILayout.Label("Ready");
+ {
+ if (GUILayout.Button("Cancel"))
+ CmdChangeReadyState(false);
+ }
else
- GUILayout.Label("Not Ready");
-
- if (((isServer && index > 0) || isServerOnly) && GUILayout.Button("REMOVE"))
{
- // This button only shows on the Host for all players other than the Host
- // Host and Players can't remove themselves (stop the client instead)
- // Host can kick a Player this way.
- GetComponent().connectionToClient.Disconnect();
+ if (GUILayout.Button("Ready"))
+ CmdChangeReadyState(true);
}
GUILayout.EndArea();
-
- if (NetworkClient.active && isLocalPlayer)
- {
- GUILayout.BeginArea(new Rect(20f, 300f, 120f, 20f));
-
- if (readyToBegin)
- {
- if (GUILayout.Button("Cancel"))
- CmdChangeReadyState(false);
- }
- else
- {
- if (GUILayout.Button("Ready"))
- CmdChangeReadyState(true);
- }
-
- GUILayout.EndArea();
- }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomPlayer.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomPlayer.cs.meta
index 3062e0e..0299bea 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomPlayer.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkRoomPlayer.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkSceneChecker.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkSceneChecker.cs
new file mode 100644
index 0000000..4e50315
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkSceneChecker.cs
@@ -0,0 +1,115 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+namespace Mirror
+{
+ ///
+ /// Component that controls visibility of networked objects between scenes.
+ /// Any object with this component on it will only be visible to other objects in the same scene
+ /// This would be used when the server has multiple additive subscenes loaded to isolate players to their respective subscenes
+ ///
+ [DisallowMultipleComponent]
+ [AddComponentMenu("Network/NetworkSceneChecker")]
+ [RequireComponent(typeof(NetworkIdentity))]
+ [HelpURL("https://mirror-networking.com/docs/Components/NetworkSceneChecker.html")]
+ public class NetworkSceneChecker : NetworkVisibility
+ {
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkSceneChecker));
+
+ ///
+ /// Flag to force this object to be hidden from all observers.
+ /// If this object is a player object, it will not be hidden for that client.
+ ///
+ [Tooltip("Enable to force this object to be hidden from all observers.")]
+ public bool forceHidden;
+
+ // Use Scene instead of string scene.name because when additively loading multiples of a subscene the name won't be unique
+ static readonly Dictionary> sceneCheckerObjects = new Dictionary>();
+
+ Scene currentScene;
+
+ [ServerCallback]
+ void Awake()
+ {
+ currentScene = gameObject.scene;
+ if (logger.LogEnabled()) logger.Log($"NetworkSceneChecker.Awake currentScene: {currentScene}");
+ }
+
+ public override void OnStartServer()
+ {
+ if (!sceneCheckerObjects.ContainsKey(currentScene))
+ sceneCheckerObjects.Add(currentScene, new HashSet());
+
+ sceneCheckerObjects[currentScene].Add(netIdentity);
+ }
+
+ [ServerCallback]
+ void Update()
+ {
+ if (currentScene == gameObject.scene)
+ return;
+
+ // This object is in a new scene so observers in the prior scene
+ // and the new scene need to rebuild their respective observers lists.
+
+ // Remove this object from the hashset of the scene it just left
+ sceneCheckerObjects[currentScene].Remove(netIdentity);
+
+ // RebuildObservers of all NetworkIdentity's in the scene this object just left
+ RebuildSceneObservers();
+
+ // Set this to the new scene this object just entered
+ currentScene = gameObject.scene;
+
+ // Make sure this new scene is in the dictionary
+ if (!sceneCheckerObjects.ContainsKey(currentScene))
+ sceneCheckerObjects.Add(currentScene, new HashSet());
+
+ // Add this object to the hashset of the new scene
+ sceneCheckerObjects[currentScene].Add(netIdentity);
+
+ // RebuildObservers of all NetworkIdentity's in the scene this object just entered
+ RebuildSceneObservers();
+ }
+
+ void RebuildSceneObservers()
+ {
+ foreach (NetworkIdentity networkIdentity in sceneCheckerObjects[currentScene])
+ if (networkIdentity != null)
+ networkIdentity.RebuildObservers(false);
+ }
+
+ ///
+ /// Callback used by the visibility system to determine if an observer (player) can see this object.
+ /// If this function returns true, the network connection will be added as an observer.
+ ///
+ /// Network connection of a player.
+ /// True if the player can see this object.
+ public override bool OnCheckObserver(NetworkConnection conn)
+ {
+ if (forceHidden)
+ return false;
+
+ return conn.identity.gameObject.scene == gameObject.scene;
+ }
+
+ ///
+ /// Callback used by the visibility system to (re)construct the set of observers that can see this object.
+ /// Implementations of this callback should add network connections of players that can see this object to the observers set.
+ ///
+ /// The new set of observers for this object.
+ /// True if the set of observers is being built for the first time.
+ public override void OnRebuildObservers(HashSet observers, bool initialize)
+ {
+ // If forceHidden then return without adding any observers.
+ if (forceHidden)
+ return;
+
+ // Add everything in the hashset for this object's current scene
+ foreach (NetworkIdentity networkIdentity in sceneCheckerObjects[currentScene])
+ if (networkIdentity != null && networkIdentity.connectionToClient != null)
+ observers.Add(networkIdentity.connectionToClient);
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkSceneChecker.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkSceneChecker.cs.meta
new file mode 100644
index 0000000..b451655
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkSceneChecker.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b7fdb599e1359924bad6255660370252
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransform.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransform.cs.meta
index d1af9ec..a569990 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransform.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransform.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformBase.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformBase.cs
index 463bee3..380a268 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformBase.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformBase.cs
@@ -16,23 +16,33 @@
// * Only way for smooth movement is to use a fixed movement speed during
// interpolation. interpolation over time is never that good.
//
-
-using System;
+using System.ComponentModel;
using UnityEngine;
namespace Mirror
{
public abstract class NetworkTransformBase : NetworkBehaviour
{
- // rotation compression. not public so that other scripts can't modify
- // it at runtime. alternatively we could send 1 extra byte for the mode
- // each time so clients know how to decompress, but the whole point was
- // to save bandwidth in the first place.
- // -> can still be modified in the Inspector while the game is running,
- // but would cause errors immediately and be pretty obvious.
- [Tooltip("Compresses 16 Byte Quaternion into None=12, Much=3, Lots=2 Bytes")]
- [SerializeField] Compression compressRotation = Compression.Much;
- public enum Compression { None, Much, Lots, NoRotation }; // easily understandable and funny
+ [Header("Authority")]
+ [Tooltip("Set to true if moves come from owner client, set to false if moves always come from server")]
+ public bool clientAuthority;
+
+ // Is this a client with authority over this transform?
+ // This component could be on the player object or any object that has been assigned authority to this client.
+ bool IsClientWithAuthority => hasAuthority && clientAuthority;
+
+ // Sensitivity is added for VR where human players tend to have micro movements so this can quiet down
+ // the network traffic. Additionally, rigidbody drift should send less traffic, e.g very slow sliding / rolling.
+ [Header("Sensitivity")]
+ [Tooltip("Changes to the transform must exceed these values to be transmitted on the network.")]
+ public float localPositionSensitivity = .01f;
+ [Tooltip("If rotation exceeds this angle, it will be transmitted on the network")]
+ public float localRotationSensitivity = .01f;
+ [Tooltip("Changes to the transform must exceed these values to be transmitted on the network.")]
+ public float localScaleSensitivity = .01f;
+
+ // target transform to sync. can be on a child.
+ protected abstract Transform targetComponent { get; }
// server
Vector3 lastPosition;
@@ -56,49 +66,24 @@ public class DataPoint
// local authority send time
float lastClientSendTime;
- // target transform to sync. can be on a child.
- protected abstract Transform targetComponent { get; }
-
// serialization is needed by OnSerialize and by manual sending from authority
- static void SerializeIntoWriter(NetworkWriter writer, Vector3 position, Quaternion rotation, Compression compressRotation, Vector3 scale)
+ // public only for tests
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static void SerializeIntoWriter(NetworkWriter writer, Vector3 position, Quaternion rotation, Vector3 scale)
{
- // serialize position
+ // serialize position, rotation, scale
+ // note: we do NOT compress rotation.
+ // we are CPU constrained, not bandwidth constrained.
+ // the code needs to WORK for the next 5-10 years of development.
writer.WriteVector3(position);
-
- // serialize rotation
- // writing quaternion = 16 byte
- // writing euler angles = 12 byte
- // -> quaternion->euler->quaternion always works.
- // -> gimbal lock only occurs when adding.
- Vector3 euler = rotation.eulerAngles;
- switch (compressRotation)
- {
- case Compression.None:
- // write 3 floats = 12 byte
- writer.WriteSingle(euler.x);
- writer.WriteSingle(euler.y);
- writer.WriteSingle(euler.z);
- break;
- case Compression.Much:
- // write 3 byte. scaling [0,360] to [0,255]
- writer.WriteByte(FloatBytePacker.ScaleFloatToByte(euler.x, 0, 360, byte.MinValue, byte.MaxValue));
- writer.WriteByte(FloatBytePacker.ScaleFloatToByte(euler.y, 0, 360, byte.MinValue, byte.MaxValue));
- writer.WriteByte(FloatBytePacker.ScaleFloatToByte(euler.z, 0, 360, byte.MinValue, byte.MaxValue));
- break;
- case Compression.Lots:
- // write 2 byte, 5 bits for each float
- writer.WriteUInt16(FloatBytePacker.PackThreeFloatsIntoUShort(euler.x, euler.y, euler.z, 0, 360));
- break;
- }
-
- // serialize scale
+ writer.WriteQuaternion(rotation);
writer.WriteVector3(scale);
}
public override bool OnSerialize(NetworkWriter writer, bool initialState)
{
// use local position/rotation/scale for VR support
- SerializeIntoWriter(writer, targetComponent.transform.localPosition, targetComponent.transform.localRotation, compressRotation, targetComponent.transform.localScale);
+ SerializeIntoWriter(writer, targetComponent.transform.localPosition, targetComponent.transform.localRotation, targetComponent.transform.localScale);
return true;
}
@@ -107,72 +92,47 @@ public override bool OnSerialize(NetworkWriter writer, bool initialState)
// => if this is the first time ever then we use our best guess:
// -> delta based on transform.localPosition
// -> elapsed based on send interval hoping that it roughly matches
- static float EstimateMovementSpeed(DataPoint from, Vector3 toPosition, float toTimestap, Transform transform, float sendInterval)
+ static float EstimateMovementSpeed(DataPoint from, DataPoint to, Transform transform, float sendInterval)
{
- Vector3 delta = toPosition - (from != null ? from.localPosition : transform.localPosition);
- float elapsed = from != null ? toTimestap - from.timeStamp : sendInterval;
- return elapsed > 0 ? delta.magnitude / elapsed : 0; // avoid NaN
+ Vector3 delta = to.localPosition - (from != null ? from.localPosition : transform.localPosition);
+ float elapsed = from != null ? to.timeStamp - from.timeStamp : sendInterval;
+ // avoid NaN
+ return elapsed > 0 ? delta.magnitude / elapsed : 0;
}
// serialization is needed by OnSerialize and by manual sending from authority
void DeserializeFromReader(NetworkReader reader)
{
// put it into a data point immediately
- Vector3 localPosition = reader.ReadVector3();
-
- // deserialize rotation
- Quaternion localRotation = default;
- switch (compressRotation)
+ DataPoint temp = new DataPoint
{
- case Compression.None:
- {
- // read 3 floats = 16 byte
- float x = reader.ReadSingle();
- float y = reader.ReadSingle();
- float z = reader.ReadSingle();
- localRotation = Quaternion.Euler(x, y, z);
- break;
- }
- case Compression.Much:
- {
- // read 3 byte. scaling [0,255] to [0,360]
- float x = FloatBytePacker.ScaleByteToFloat(reader.ReadByte(), byte.MinValue, byte.MaxValue, 0, 360);
- float y = FloatBytePacker.ScaleByteToFloat(reader.ReadByte(), byte.MinValue, byte.MaxValue, 0, 360);
- float z = FloatBytePacker.ScaleByteToFloat(reader.ReadByte(), byte.MinValue, byte.MaxValue, 0, 360);
- localRotation = Quaternion.Euler(x, y, z);
- break;
- }
- case Compression.Lots:
- {
- // read 2 byte, 5 bits per float
- Vector3 xyz = FloatBytePacker.UnpackUShortIntoThreeFloats(reader.ReadUInt16(), 0, 360);
- localRotation = Quaternion.Euler(xyz.x, xyz.y, xyz.z);
- break;
- }
- }
+ // deserialize position
+ localPosition = reader.ReadVector3()
+ };
- Vector3 localScale = reader.ReadVector3();
+ // deserialize rotation & scale
+ temp.localRotation = reader.ReadQuaternion();
+ temp.localScale = reader.ReadVector3();
- float timeStamp = Time.time;
+ temp.timeStamp = Time.time;
// movement speed: based on how far it moved since last time
// has to be calculated before 'start' is overwritten
- float movementSpeed = EstimateMovementSpeed(goal, localPosition, timeStamp, targetComponent.transform, syncInterval);
+ temp.movementSpeed = EstimateMovementSpeed(goal, temp, targetComponent.transform, syncInterval);
// reassign start wisely
// -> first ever data point? then make something up for previous one
// so that we can start interpolation without waiting for next.
if (start == null)
{
- Transform pos = targetComponent.transform;
start = new DataPoint
{
timeStamp = Time.time - syncInterval,
// local position/rotation for VR support
- localPosition = pos.localPosition,
- localRotation = pos.localRotation,
- localScale = pos.localScale,
- movementSpeed = movementSpeed
+ localPosition = targetComponent.transform.localPosition,
+ localRotation = targetComponent.transform.localRotation,
+ localScale = targetComponent.transform.localScale,
+ movementSpeed = temp.movementSpeed
};
}
// -> second or nth data point? then update previous, but:
@@ -207,38 +167,24 @@ void DeserializeFromReader(NetworkReader reader)
else
{
float oldDistance = Vector3.Distance(start.localPosition, goal.localPosition);
- float newDistance = Vector3.Distance(goal.localPosition, localPosition);
+ float newDistance = Vector3.Distance(goal.localPosition, temp.localPosition);
- start.localPosition = goal.localPosition;
- start.localRotation = goal.localRotation;
- start.localScale = goal.localScale;
- start.movementSpeed = goal.movementSpeed;
- start.timeStamp = goal.timeStamp;
+ start = goal;
// teleport / lag / obstacle detection: only continue at current
// position if we aren't too far away
//
- // // local position/rotation for VR support
- Transform pos = targetComponent.transform;
- if (Vector3.Distance(pos.localPosition, start.localPosition) < oldDistance + newDistance)
+ // local position/rotation for VR support
+ if (Vector3.Distance(targetComponent.transform.localPosition, start.localPosition) < oldDistance + newDistance)
{
- start.localPosition = pos.localPosition;
- start.localRotation = pos.localRotation;
- start.localScale = pos.localScale;
+ start.localPosition = targetComponent.transform.localPosition;
+ start.localRotation = targetComponent.transform.localRotation;
+ start.localScale = targetComponent.transform.localScale;
}
}
// set new destination in any case. new data is best data.
- if (goal == null)
- {
- goal = new DataPoint();
- }
-
- goal.localPosition = localPosition;
- goal.localRotation = localRotation;
- goal.localScale = localScale;
- goal.movementSpeed = movementSpeed;
- goal.timeStamp = timeStamp;
+ goal = temp;
}
public override void OnDeserialize(NetworkReader reader, bool initialState)
@@ -249,12 +195,15 @@ public override void OnDeserialize(NetworkReader reader, bool initialState)
// local authority client sends sync message to server for broadcasting
[Command]
- void CmdClientToServerSync(ArraySegment payload)
+ void CmdClientToServerSync(byte[] payload)
{
+ // Ignore messages from client if not in client authority mode
+ if (!clientAuthority)
+ return;
+
// deserialize payload
- NetworkReader reader = NetworkReaderPool.GetReader(payload);
- DeserializeFromReader(reader);
- NetworkReaderPool.Recycle(reader);
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(payload))
+ DeserializeFromReader(networkReader);
// server-only mode does no interpolation to save computations,
// but let's set the position directly
@@ -275,7 +224,8 @@ static float CurrentInterpolationFactor(DataPoint start, DataPoint goal)
// the moment we get 'goal', 'start' is supposed to
// start, so elapsed time is based on:
float elapsed = Time.time - goal.timeStamp;
- return difference > 0 ? elapsed / difference : 0; // avoid NaN
+ // avoid NaN
+ return difference > 0 ? elapsed / difference : 0;
}
return 0;
}
@@ -339,9 +289,9 @@ bool HasEitherMovedRotatedScaled()
{
// moved or rotated or scaled?
// local position/rotation/scale for VR support
- bool moved = lastPosition != targetComponent.transform.localPosition;
- bool rotated = lastRotation != targetComponent.transform.localRotation;
- bool scaled = lastScale != targetComponent.transform.localScale;
+ bool moved = Vector3.Distance(lastPosition, targetComponent.transform.localPosition) > localPositionSensitivity;
+ bool scaled = Vector3.Distance(lastScale, targetComponent.transform.localScale) > localScaleSensitivity;
+ bool rotated = Quaternion.Angle(lastRotation, targetComponent.transform.localRotation) > localRotationSensitivity;
// save last for next frame to compare
// (only if change was detected. otherwise slow moving objects might
@@ -363,10 +313,7 @@ void ApplyPositionRotationScale(Vector3 position, Quaternion rotation, Vector3 s
{
// local position/rotation for VR support
targetComponent.transform.localPosition = position;
- if (Compression.NoRotation != compressRotation)
- {
- targetComponent.transform.localRotation = rotation;
- }
+ targetComponent.transform.localRotation = rotation;
targetComponent.transform.localScale = scale;
}
@@ -385,7 +332,7 @@ void Update()
{
// send to server if we have local authority (and aren't the server)
// -> only if connectionToServer has been initialized yet too
- if (!isServer && hasAuthority)
+ if (!isServer && IsClientWithAuthority)
{
// check only each 'syncInterval'
if (Time.time - lastClientSendTime >= syncInterval)
@@ -394,12 +341,13 @@ void Update()
{
// serialize
// local position/rotation for VR support
- NetworkWriter writer = NetworkWriterPool.GetWriter();
- SerializeIntoWriter(writer, targetComponent.transform.localPosition, targetComponent.transform.localRotation, compressRotation, targetComponent.transform.localScale);
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
+ {
+ SerializeIntoWriter(writer, targetComponent.transform.localPosition, targetComponent.transform.localRotation, targetComponent.transform.localScale);
- // send to server
- CmdClientToServerSync(writer.ToArraySegment());
- NetworkWriterPool.Recycle(writer);
+ // send to server
+ CmdClientToServerSync(writer.ToArray());
+ }
}
lastClientSendTime = Time.time;
}
@@ -408,7 +356,7 @@ void Update()
// apply interpolation on client for all players
// unless this client has authority over the object. could be
// himself or another object that he was assigned authority over
- if (!hasAuthority)
+ if (!IsClientWithAuthority)
{
// received one yet? (initialized?)
if (goal != null)
@@ -418,6 +366,10 @@ void Update()
{
// local position/rotation for VR support
ApplyPositionRotationScale(goal.localPosition, goal.localRotation, goal.localScale);
+
+ // reset data points so we don't keep interpolating
+ start = null;
+ goal = null;
}
else
{
@@ -442,10 +394,12 @@ static void DrawDataPointGizmo(DataPoint data, Color color)
Gizmos.DrawSphere(data.localPosition + offset, 0.5f);
// draw forward and up
- Gizmos.color = Color.blue; // like unity move tool
+ // like unity move tool
+ Gizmos.color = Color.blue;
Gizmos.DrawRay(data.localPosition + offset, data.localRotation * Vector3.forward);
- Gizmos.color = Color.green; // like unity move tool
+ // like unity move tool
+ Gizmos.color = Color.green;
Gizmos.DrawRay(data.localPosition + offset, data.localRotation * Vector3.up);
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformBase.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformBase.cs.meta
index 2c3c3e1..ab649d9 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformBase.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformBase.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformChild.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformChild.cs
index 84e8b05..84a0d31 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformChild.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformChild.cs
@@ -10,7 +10,9 @@ namespace Mirror
[HelpURL("https://mirror-networking.com/docs/Components/NetworkTransformChild.html")]
public class NetworkTransformChild : NetworkTransformBase
{
+ [Header("Target")]
public Transform target;
+
protected override Transform targetComponent => target;
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformChild.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformChild.cs.meta
index 9c068f2..ae36756 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformChild.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Components/NetworkTransformChild.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/EnterPlayModeSettingsCheck.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/EnterPlayModeSettingsCheck.cs
new file mode 100644
index 0000000..30b1acd
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/EnterPlayModeSettingsCheck.cs
@@ -0,0 +1,74 @@
+// Unity 2019.3 has an experimental 'disable domain reload on play'
+// feature. keeping any global state between sessions will break
+// Mirror and most of our user's projects. don't allow it for now.
+// https://blogs.unity3d.com/2019/11/05/enter-play-mode-faster-in-unity-2019-3/
+using UnityEditor;
+using UnityEngine;
+
+namespace Mirror
+{
+ public class EnterPlayModeSettingsCheck : MonoBehaviour
+ {
+ [InitializeOnLoadMethod]
+ static void OnInitializeOnLoad()
+ {
+#if UNITY_2019_3_OR_NEWER
+ // We can't support experimental "Enter Play Mode Options" mode
+ // Check immediately on load, and before entering play mode, and warn the user
+ CheckPlayModeOptions();
+#endif
+
+ // Hook this event to see if we have a good weave every time
+ // user attempts to enter play mode or tries to do a build
+ EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
+ }
+
+ static void OnPlayModeStateChanged(PlayModeStateChange state)
+ {
+ // Per Unity docs, this fires "when exiting edit mode before the Editor is in play mode".
+ // This doesn't fire when closing the editor.
+ if (state == PlayModeStateChange.ExitingEditMode)
+ {
+ CheckSuccessfulWeave();
+
+#if UNITY_2019_3_OR_NEWER
+ // We can't support experimental "Enter Play Mode Options" mode
+ // Check and prevent entering play mode if enabled
+ CheckPlayModeOptions();
+#endif
+ }
+ }
+
+ static void CheckSuccessfulWeave()
+ {
+ // Check if last weave result was successful
+ if (!SessionState.GetBool("MIRROR_WEAVE_SUCCESS", false))
+ {
+ // Last weave result was a failure...try to weave again
+ // Faults will show in the console that may have been cleared by "Clear on Play"
+ SessionState.SetBool("MIRROR_WEAVE_SUCCESS", true);
+ Weaver.CompilationFinishedHook.WeaveExistingAssemblies();
+
+ // Did that clear things up for us?
+ if (!SessionState.GetBool("MIRROR_WEAVE_SUCCESS", false))
+ {
+ // Nope, still failed, and console has the issues logged
+ Debug.LogError("Can't enter play mode until weaver issues are resolved.");
+ EditorApplication.isPlaying = false;
+ }
+ }
+ }
+
+#if UNITY_2019_3_OR_NEWER
+ static void CheckPlayModeOptions()
+ {
+ // enabling the checkbox is enough. it controls all the other settings.
+ if (EditorSettings.enterPlayModeOptionsEnabled)
+ {
+ Debug.LogError("Enter Play Mode Options are not supported by Mirror. Please disable 'ProjectSettings -> Editor -> Enter Play Mode Settings (Experimental)'.");
+ EditorApplication.isPlaying = false;
+ }
+ }
+#endif
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/EnterPlayModeSettingsCheck.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/EnterPlayModeSettingsCheck.cs.meta
new file mode 100644
index 0000000..79a200d
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/EnterPlayModeSettingsCheck.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b15a0d2ca0909400eb53dd6fe894cddd
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/InspectorHelper.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/InspectorHelper.cs
new file mode 100644
index 0000000..40d2f1e
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/InspectorHelper.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEngine;
+
+namespace Mirror
+{
+ public static class InspectorHelper
+ {
+ ///
+ /// Gets all public and private fields for a type
+ ///
+ ///
+ /// Stops at this base type (exclusive)
+ ///
+ public static IEnumerable GetAllFields(Type type, Type deepestBaseType)
+ {
+ const BindingFlags publicFields = BindingFlags.Public | BindingFlags.Instance;
+ const BindingFlags privateFields = BindingFlags.NonPublic | BindingFlags.Instance;
+
+ // get public fields (includes fields from base type)
+ FieldInfo[] allPublicFields = type.GetFields(publicFields);
+ foreach (FieldInfo field in allPublicFields)
+ {
+ yield return field;
+ }
+
+ // get private fields in current type, then move to base type
+ while (type != null)
+ {
+ FieldInfo[] allPrivateFields = type.GetFields(privateFields);
+ foreach (FieldInfo field in allPrivateFields)
+ {
+ yield return field;
+ }
+
+ type = type.BaseType;
+
+ // stop early
+ if (type == deepestBaseType)
+ {
+ break;
+ }
+ }
+ }
+
+ public static bool IsSyncVar(this FieldInfo field)
+ {
+ object[] fieldMarkers = field.GetCustomAttributes(typeof(SyncVarAttribute), true);
+ return fieldMarkers.Length > 0;
+ }
+ public static bool IsSerializeField(this FieldInfo field)
+ {
+ object[] fieldMarkers = field.GetCustomAttributes(typeof(SerializeField), true);
+ return fieldMarkers.Length > 0;
+ }
+ public static bool IsVisibleField(this FieldInfo field)
+ {
+ return field.IsPublic || IsSerializeField(field);
+ }
+
+ public static bool IsSyncObject(this FieldInfo field)
+ {
+ return typeof(SyncObject).IsAssignableFrom(field.FieldType);
+ }
+ public static bool HasShowInInspector(this FieldInfo field)
+ {
+ object[] fieldMarkers = field.GetCustomAttributes(typeof(ShowInInspectorAttribute), true);
+ return fieldMarkers.Length > 0;
+ }
+ public static bool IsVisibleSyncObject(this FieldInfo field)
+ {
+ return field.IsPublic || HasShowInInspector(field);
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/InspectorHelper.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/InspectorHelper.cs.meta
new file mode 100644
index 0000000..852ff71
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/InspectorHelper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 047c894c2a5ccc1438b7e59302f62744
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/LogLevelWindow.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/LogLevelWindow.cs
new file mode 100644
index 0000000..82e5275
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/LogLevelWindow.cs
@@ -0,0 +1 @@
+// File moved to Mirror/Editor/Logging/LogLevelWindow.cs
\ No newline at end of file
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/LogLevelWindow.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/LogLevelWindow.cs.meta
new file mode 100644
index 0000000..b8cbaeb
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/LogLevelWindow.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f28def2148ed5194abe70af012a4e3e0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging.meta
new file mode 100644
index 0000000..257467f
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4d97731cd74ac8b4b8aad808548ef9cd
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelWindow.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelWindow.cs
new file mode 100644
index 0000000..1d80f52
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelWindow.cs
@@ -0,0 +1,70 @@
+using Mirror.Logging;
+using UnityEditor;
+using UnityEngine;
+
+namespace Mirror.EditorScripts.Logging
+{
+ public class LogLevelWindow : EditorWindow
+ {
+ [Header("Log Settings Asset")]
+ [SerializeField] LogSettings settings = null;
+
+ SerializedObject serializedObject;
+ SerializedProperty settingsProp;
+ Vector2 dictionaryScrollPosition;
+
+ void OnEnable()
+ {
+ serializedObject = new SerializedObject(this);
+ settingsProp = serializedObject.FindProperty(nameof(settings));
+
+ LogSettings existingSettings = EditorLogSettingsLoader.FindLogSettings();
+ if (existingSettings != null)
+ {
+ settingsProp.objectReferenceValue = existingSettings;
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+
+ void OnGUI()
+ {
+ using (EditorGUILayout.ScrollViewScope scrollScope = new EditorGUILayout.ScrollViewScope(dictionaryScrollPosition, GUIStyle.none, GUI.skin.verticalScrollbar))
+ {
+ dictionaryScrollPosition = scrollScope.scrollPosition;
+
+ using (new EditorGUILayout.VerticalScope())
+ {
+ using (new EditorGUILayout.VerticalScope())
+ {
+ serializedObject.Update();
+ EditorGUILayout.PropertyField(settingsProp);
+ serializedObject.ApplyModifiedProperties();
+
+ if (settings == null)
+ {
+ LogSettings newSettings = LogLevelsGUI.DrawCreateNewButton();
+ if (newSettings != null)
+ {
+ settingsProp.objectReferenceValue = newSettings;
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+ else
+ {
+ LogLevelsGUI.DrawLogFactoryDictionary(settings);
+ }
+ }
+ }
+ }
+ }
+
+ [MenuItem("Window/Analysis/Mirror Log Levels", priority = 20002)]
+ public static void ShowWindow()
+ {
+ LogLevelWindow window = GetWindow();
+ window.minSize = new Vector2(200, 100);
+ window.titleContent = new GUIContent("Mirror Log Levels");
+ window.Show();
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelWindow.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelWindow.cs.meta
new file mode 100644
index 0000000..832876f
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelWindow.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c3dbf48190d77d243b87962a82c3b164
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelsGUI.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelsGUI.cs
new file mode 100644
index 0000000..2aaa855
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelsGUI.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+using Mirror.Logging;
+using UnityEditor;
+using UnityEngine;
+
+namespace Mirror.EditorScripts.Logging
+{
+ public static class LogLevelsGUI
+ {
+ public static LogSettings DrawCreateNewButton()
+ {
+ if (GUILayout.Button("Create New"))
+ {
+ return ScriptableObjectUtility.CreateAsset(nameof(LogSettings));
+ }
+
+ return null;
+ }
+
+ public static void DrawLogFactoryDictionary(LogSettings settings)
+ {
+ using (EditorGUI.ChangeCheckScope scope = new EditorGUI.ChangeCheckScope())
+ {
+ if (LogFactory.loggers.Count == 0)
+ {
+ EditorGUILayout.LabelField("No Keys found in LogFactory.loggers\nPlay the game for default log values to be added to LogFactory", EditorStyles.wordWrappedLabel);
+ }
+ else
+ {
+ EditorGUILayout.Space();
+ EditorGUILayout.LabelField("Logging Components", EditorStyles.boldLabel);
+
+ foreach (KeyValuePair item in LogFactory.loggers)
+ {
+ DrawLoggerField(item);
+ }
+
+ if (scope.changed)
+ {
+ settings.SaveFromDictionary(LogFactory.loggers);
+ }
+ }
+ }
+ }
+
+ static void DrawLoggerField(KeyValuePair item)
+ {
+ ILogger logger = item.Value;
+ string name = item.Key;
+
+ const float fieldWidth = 100f;
+ const float inspectorMargin = 25f;
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ EditorGUILayout.LabelField(new GUIContent(ObjectNames.NicifyVariableName(name)), GUILayout.MaxWidth(EditorGUIUtility.currentViewWidth - fieldWidth - inspectorMargin));
+ logger.filterLogType = (LogType)EditorGUILayout.EnumPopup(logger.filterLogType, GUILayout.Width(fieldWidth));
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelsGUI.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelsGUI.cs.meta
new file mode 100644
index 0000000..3214b08
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogLevelsGUI.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9d6ce9d62a2d2ec4d8cef8a0d22b8dd2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogSettingsEditor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogSettingsEditor.cs
new file mode 100644
index 0000000..2579ae4
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogSettingsEditor.cs
@@ -0,0 +1,24 @@
+using Mirror.Logging;
+using UnityEditor;
+using UnityEngine;
+
+namespace Mirror.EditorScripts.Logging
+{
+ [CustomEditor(typeof(LogSettings))]
+ public class LogSettingsEditor : Editor
+ {
+ public override void OnInspectorGUI()
+ {
+ CurrentScriptField();
+
+ LogLevelsGUI.DrawLogFactoryDictionary(target as LogSettings);
+ }
+
+ public void CurrentScriptField()
+ {
+ GUI.enabled = false;
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Script"));
+ GUI.enabled = true;
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogSettingsEditor.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogSettingsEditor.cs.meta
new file mode 100644
index 0000000..2c1fac4
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/LogSettingsEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8f4ecb3d81ce9ff44b91f311ee46d4ea
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/NetworkLogSettingsEditor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/NetworkLogSettingsEditor.cs
new file mode 100644
index 0000000..56e172f
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/NetworkLogSettingsEditor.cs
@@ -0,0 +1,31 @@
+using Mirror.Logging;
+using UnityEditor;
+
+namespace Mirror.EditorScripts.Logging
+{
+ [CustomEditor(typeof(NetworkLogSettings))]
+ public class NetworkLogSettingsEditor : Editor
+ {
+ public override void OnInspectorGUI()
+ {
+ DrawDefaultInspector();
+
+ NetworkLogSettings target = this.target as NetworkLogSettings;
+
+ if (target.settings == null)
+ {
+ LogSettings newSettings = LogLevelsGUI.DrawCreateNewButton();
+ if (newSettings != null)
+ {
+ SerializedProperty settingsProp = serializedObject.FindProperty("settings");
+ settingsProp.objectReferenceValue = newSettings;
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+ else
+ {
+ LogLevelsGUI.DrawLogFactoryDictionary(target.settings);
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/NetworkLogSettingsEditor.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/NetworkLogSettingsEditor.cs.meta
new file mode 100644
index 0000000..b4c277d
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Logging/NetworkLogSettingsEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 37fb96d5bbf965d47acfc5c8589a1b71
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Mirror.Editor.asmdef b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Mirror.Editor.asmdef
index d18558b..3ed7e2f 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Mirror.Editor.asmdef
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Mirror.Editor.asmdef
@@ -1,7 +1,8 @@
{
"name": "Mirror.Editor",
"references": [
- "Mirror"
+ "Mirror",
+ "Mirror.Weaver"
],
"optionalUnityReferences": [],
"includePlatforms": [
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkAnimatorEditor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkAnimatorEditor.cs
deleted file mode 100644
index 20db50b..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkAnimatorEditor.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-// This file was removed in Mirror 3.4.9
-// The purpose of this file is to get the old file overwritten
-// when users update from the asset store to prevent a flood of errors
-// from having the old file still in the project as a straggler.
-// This file will be dropped from the Asset Store package in May 2019
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkBehaviourInspector.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkBehaviourInspector.cs
index 1672875..45740a0 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkBehaviourInspector.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkBehaviourInspector.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
@@ -12,18 +11,25 @@ namespace Mirror
[CanEditMultipleObjects]
public class NetworkBehaviourInspector : Editor
{
- bool initialized;
+ ///
+ /// List of all visible syncVars in target class
+ ///
protected List syncVarNames = new List();
bool syncsAnything;
- bool[] showSyncLists;
-
- readonly GUIContent syncVarIndicatorContent = new GUIContent("SyncVar", "This variable has been marked with the [SyncVar] attribute.");
-
- internal virtual bool HideScriptField => false;
+ SyncListDrawer syncListDrawer;
// does this type sync anything? otherwise we don't need to show syncInterval
bool SyncsAnything(Type scriptClass)
{
+ // check for all SyncVar fields, they don't have to be visible
+ foreach (FieldInfo field in InspectorHelper.GetAllFields(scriptClass, typeof(NetworkBehaviour)))
+ {
+ if (field.IsSyncVar())
+ {
+ return true;
+ }
+ }
+
// has OnSerialize that is not in NetworkBehaviour?
// then it either has a syncvar or custom OnSerialize. either way
// this means we have something to sync.
@@ -36,163 +42,144 @@ bool SyncsAnything(Type scriptClass)
// SyncObjects are serialized in NetworkBehaviour.OnSerialize, which
// is always there even if we don't use SyncObjects. so we need to
// search for SyncObjects manually.
- // (look for 'Mirror.Sync'. not '.SyncObject' because we'd have to
- // check base type for that again)
- // => scan both public and non-public fields! SyncVars can be private
- BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
- foreach (FieldInfo field in scriptClass.GetFields(flags))
- {
- if (field.FieldType.BaseType != null &&
- field.FieldType.BaseType.FullName != null &&
- field.FieldType.BaseType.FullName.Contains("Mirror.Sync"))
- {
- return true;
- }
- }
+ // Any SyncObject should be added to syncObjects when unity creates an
+ // object so we can cheeck length of list so see if sync objects exists
+ FieldInfo syncObjectsField = scriptClass.GetField("syncObjects", BindingFlags.NonPublic | BindingFlags.Instance);
+ List syncObjects = (List)syncObjectsField.GetValue(serializedObject.targetObject);
- return false;
+ return syncObjects.Count > 0;
}
- void Init(MonoScript script)
+ void OnEnable()
{
- initialized = true;
- Type scriptClass = script.GetClass();
+ if (target == null) { Debug.LogWarning("NetworkBehaviourInspector had no target object"); return; }
+
+ // If target's base class is changed from NetworkBehaviour to MonoBehaviour
+ // then Unity temporarily keep using this Inspector causing things to break
+ if (!(target is NetworkBehaviour)) { return; }
- // find public SyncVars to show (user doesn't want protected ones to be shown in inspector)
- foreach (FieldInfo field in scriptClass.GetFields(BindingFlags.Public | BindingFlags.Instance))
+ Type scriptClass = target.GetType();
+
+ syncVarNames = new List();
+ foreach (FieldInfo field in InspectorHelper.GetAllFields(scriptClass, typeof(NetworkBehaviour)))
{
- Attribute[] fieldMarkers = (Attribute[])field.GetCustomAttributes(typeof(SyncVarAttribute), true);
- if (fieldMarkers.Length > 0)
+ if (field.IsSyncVar() && field.IsVisibleField())
{
syncVarNames.Add(field.Name);
}
}
- int numSyncLists = scriptClass.GetFields().Count(
- field => field.FieldType.BaseType != null &&
- field.FieldType.BaseType.Name.Contains("SyncList"));
- if (numSyncLists > 0)
- {
- showSyncLists = new bool[numSyncLists];
- }
+ syncListDrawer = new SyncListDrawer(serializedObject.targetObject);
syncsAnything = SyncsAnything(scriptClass);
}
public override void OnInspectorGUI()
{
- if (!initialized)
- {
- serializedObject.Update();
- SerializedProperty scriptProperty = serializedObject.FindProperty("m_Script");
- if (scriptProperty == null)
- return;
+ DrawDefaultInspector();
+ DrawDefaultSyncLists();
+ DrawDefaultSyncSettings();
+ }
- MonoScript targetScript = scriptProperty.objectReferenceValue as MonoScript;
- Init(targetScript);
- }
+ ///
+ /// Draws Sync Objects that are IEnumerable
+ ///
+ protected void DrawDefaultSyncLists()
+ {
+ // Need this check incase OnEnable returns early
+ if (syncListDrawer == null) { return; }
- EditorGUI.BeginChangeCheck();
- serializedObject.Update();
+ syncListDrawer.Draw();
+ }
- // Loop through properties and create one field (including children) for each top level property.
- SerializedProperty property = serializedObject.GetIterator();
- bool expanded = true;
- while (property.NextVisible(expanded))
+ ///
+ /// Draws SyncSettings if the NetworkBehaviour has anything to sync
+ ///
+ protected void DrawDefaultSyncSettings()
+ {
+ // does it sync anything? then show extra properties
+ // (no need to show it if the class only has Cmds/Rpcs and no sync)
+ if (!syncsAnything)
{
- bool isSyncVar = syncVarNames.Contains(property.name);
- if (property.propertyType == SerializedPropertyType.ObjectReference)
- {
- if (property.name == "m_Script")
- {
- if (HideScriptField)
- {
- continue;
- }
+ return;
+ }
- EditorGUI.BeginDisabledGroup(true);
- }
+ EditorGUILayout.Space();
+ EditorGUILayout.LabelField("Sync Settings", EditorStyles.boldLabel);
- EditorGUILayout.PropertyField(property, true);
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("syncMode"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("syncInterval"));
- if (isSyncVar)
- {
- GUILayout.Label(syncVarIndicatorContent, EditorStyles.miniLabel, GUILayout.Width(EditorStyles.miniLabel.CalcSize(syncVarIndicatorContent).x));
- }
+ // apply
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+ public class SyncListDrawer
+ {
+ readonly UnityEngine.Object targetObject;
+ readonly List syncListFields;
- if (property.name == "m_Script")
- {
- EditorGUI.EndDisabledGroup();
- }
- }
- else
+ public SyncListDrawer(UnityEngine.Object targetObject)
+ {
+ this.targetObject = targetObject;
+ syncListFields = new List();
+ foreach (FieldInfo field in InspectorHelper.GetAllFields(targetObject.GetType(), typeof(NetworkBehaviour)))
+ {
+ if (field.IsSyncObject() && field.IsVisibleSyncObject())
{
- EditorGUILayout.BeginHorizontal();
+ syncListFields.Add(new SyncListField(field));
+ }
+ }
+ }
- EditorGUILayout.PropertyField(property, true);
+ public void Draw()
+ {
+ if (syncListFields.Count == 0) { return; }
- if (isSyncVar)
- {
- GUILayout.Label(syncVarIndicatorContent, EditorStyles.miniLabel, GUILayout.Width(EditorStyles.miniLabel.CalcSize(syncVarIndicatorContent).x));
- }
+ EditorGUILayout.Space();
+ EditorGUILayout.LabelField("Sync Lists", EditorStyles.boldLabel);
- EditorGUILayout.EndHorizontal();
- }
- expanded = false;
+ for (int i = 0; i < syncListFields.Count; i++)
+ {
+ DrawSyncList(syncListFields[i]);
}
- serializedObject.ApplyModifiedProperties();
- EditorGUI.EndChangeCheck();
+ }
- // find SyncLists.. they are not properties.
- int syncListIndex = 0;
- foreach (FieldInfo field in serializedObject.targetObject.GetType().GetFields())
+ void DrawSyncList(SyncListField syncListField)
+ {
+ syncListField.visible = EditorGUILayout.Foldout(syncListField.visible, syncListField.label);
+ if (syncListField.visible)
{
- if (field.FieldType.BaseType != null && field.FieldType.BaseType.Name.Contains("SyncList"))
+ using (new EditorGUI.IndentLevelScope())
{
- showSyncLists[syncListIndex] = EditorGUILayout.Foldout(showSyncLists[syncListIndex], "SyncList " + field.Name + " [" + field.FieldType.Name + "]");
- if (showSyncLists[syncListIndex])
+ object fieldValue = syncListField.field.GetValue(targetObject);
+ if (fieldValue is IEnumerable synclist)
{
- EditorGUI.indentLevel += 1;
- if (field.GetValue(serializedObject.targetObject) is IEnumerable synclist)
+ int index = 0;
+ foreach (object item in synclist)
{
- int index = 0;
- IEnumerator enu = synclist.GetEnumerator();
- while (enu.MoveNext())
- {
- if (enu.Current != null)
- {
- EditorGUILayout.LabelField("Item:" + index, enu.Current.ToString());
- }
- index += 1;
- }
+ string itemValue = item != null ? item.ToString() : "NULL";
+ string itemLabel = "Element " + index;
+ EditorGUILayout.LabelField(itemLabel, itemValue);
+
+ index++;
}
- EditorGUI.indentLevel -= 1;
}
- syncListIndex += 1;
}
}
+ }
- // does it sync anything? then show extra properties
- // (no need to show it if the class only has Cmds/Rpcs and no sync)
- if (syncsAnything)
+ class SyncListField
+ {
+ public bool visible;
+ public readonly FieldInfo field;
+ public readonly string label;
+
+ public SyncListField(FieldInfo field)
{
- NetworkBehaviour networkBehaviour = target as NetworkBehaviour;
- if (networkBehaviour != null)
- {
- // syncMode
- serializedObject.FindProperty("syncMode").enumValueIndex = (int)(SyncMode)
- EditorGUILayout.EnumPopup("Network Sync Mode", networkBehaviour.syncMode);
-
- // syncInterval
- // [0,2] should be enough. anything >2s is too laggy anyway.
- serializedObject.FindProperty("syncInterval").floatValue = EditorGUILayout.Slider(
- new GUIContent("Network Sync Interval",
- "Time in seconds until next change is synchronized to the client. '0' means send immediately if changed. '0.5' means only send changes every 500ms.\n(This is for state synchronization like SyncVars, SyncLists, OnSerialize. Not for Cmds, Rpcs, etc.)"),
- networkBehaviour.syncInterval, 0, 2);
-
- // apply
- serializedObject.ApplyModifiedProperties();
- }
+ this.field = field;
+ visible = false;
+ label = field.Name + " [" + field.FieldType.Name + "]";
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkIdentityEditor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkIdentityEditor.cs
deleted file mode 100644
index 4b2d12d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkIdentityEditor.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using System.Collections.Generic;
-using UnityEditor;
-using UnityEngine;
-
-namespace Mirror
-{
- [CustomEditor(typeof(NetworkIdentity), true)]
- [CanEditMultipleObjects]
- public class NetworkIdentityEditor : Editor
- {
- SerializedProperty serverOnlyProperty;
- SerializedProperty localPlayerAuthorityProperty;
-
- readonly GUIContent serverOnlyLabel = new GUIContent("Server Only", "True if the object should only exist on the server.");
- readonly GUIContent localPlayerAuthorityLabel = new GUIContent("Local Player Authority", "True if this object will be controlled by a player on a client.");
- readonly GUIContent spawnLabel = new GUIContent("Spawn Object", "This causes an unspawned server object to be spawned on clients");
-
- NetworkIdentity networkIdentity;
- bool initialized;
- bool showObservers;
-
- void Init()
- {
- if (initialized)
- {
- return;
- }
- initialized = true;
- networkIdentity = target as NetworkIdentity;
-
- serverOnlyProperty = serializedObject.FindProperty("serverOnly");
- localPlayerAuthorityProperty = serializedObject.FindProperty("localPlayerAuthority");
- }
-
- public override void OnInspectorGUI()
- {
- if (serverOnlyProperty == null)
- {
- initialized = false;
- }
-
- Init();
-
- serializedObject.Update();
-
- if (serverOnlyProperty.boolValue)
- {
- EditorGUILayout.PropertyField(serverOnlyProperty, serverOnlyLabel);
- EditorGUILayout.LabelField("Local Player Authority cannot be set for server-only objects");
- }
- else if (localPlayerAuthorityProperty.boolValue)
- {
- EditorGUILayout.LabelField("Server Only cannot be set for Local Player Authority objects");
- EditorGUILayout.PropertyField(localPlayerAuthorityProperty, localPlayerAuthorityLabel);
- }
- else
- {
- EditorGUILayout.PropertyField(serverOnlyProperty, serverOnlyLabel);
- EditorGUILayout.PropertyField(localPlayerAuthorityProperty, localPlayerAuthorityLabel);
- }
-
- serializedObject.ApplyModifiedProperties();
-
- if (!Application.isPlaying)
- {
- return;
- }
-
- // Runtime actions below here
-
- EditorGUILayout.Separator();
-
- if (networkIdentity.observers != null && networkIdentity.observers.Count > 0)
- {
- showObservers = EditorGUILayout.Foldout(showObservers, "Observers");
- if (showObservers)
- {
- EditorGUI.indentLevel += 1;
- foreach (KeyValuePair kvp in networkIdentity.observers)
- {
- if (kvp.Value.identity != null)
- EditorGUILayout.ObjectField("Connection " + kvp.Value.connectionId, kvp.Value.identity.gameObject, typeof(GameObject), false);
- else
- EditorGUILayout.TextField("Connection " + kvp.Value.connectionId);
- }
- EditorGUI.indentLevel -= 1;
- }
- }
-
- if (PrefabUtility.IsPartOfPrefabAsset(networkIdentity.gameObject))
- return;
-
- if (networkIdentity.gameObject.activeSelf && networkIdentity.netId == 0 && NetworkServer.active)
- {
- EditorGUILayout.BeginHorizontal();
- EditorGUILayout.LabelField(spawnLabel);
- if (GUILayout.Toggle(false, "Spawn", EditorStyles.miniButtonLeft))
- {
- NetworkServer.Spawn(networkIdentity.gameObject);
- EditorUtility.SetDirty(target); // preview window STILL doens't update immediately..
- }
- EditorGUILayout.EndHorizontal();
- }
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkInformationPreview.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkInformationPreview.cs
index 9699f6d..0c30298 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkInformationPreview.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkInformationPreview.cs
@@ -1,20 +1,19 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
-using UnityObject = UnityEngine.Object;
namespace Mirror
{
[CustomPreview(typeof(GameObject))]
class NetworkInformationPreview : ObjectPreview
{
- class NetworkIdentityInfo
+ struct NetworkIdentityInfo
{
public GUIContent name;
public GUIContent value;
}
- class NetworkBehaviourInfo
+ struct NetworkBehaviourInfo
{
// This is here just so we can check if it's enabled/disabled
public NetworkBehaviour behaviour;
@@ -31,14 +30,14 @@ public Styles()
{
Color fontColor = new Color(0.7f, 0.7f, 0.7f);
labelStyle.padding.right += 20;
- labelStyle.normal.textColor = fontColor;
- labelStyle.active.textColor = fontColor;
- labelStyle.focused.textColor = fontColor;
- labelStyle.hover.textColor = fontColor;
- labelStyle.onNormal.textColor = fontColor;
- labelStyle.onActive.textColor = fontColor;
+ labelStyle.normal.textColor = fontColor;
+ labelStyle.active.textColor = fontColor;
+ labelStyle.focused.textColor = fontColor;
+ labelStyle.hover.textColor = fontColor;
+ labelStyle.onNormal.textColor = fontColor;
+ labelStyle.onActive.textColor = fontColor;
labelStyle.onFocused.textColor = fontColor;
- labelStyle.onHover.textColor = fontColor;
+ labelStyle.onHover.textColor = fontColor;
componentName.normal.textColor = fontColor;
componentName.active.textColor = fontColor;
@@ -60,18 +59,9 @@ public Styles()
}
}
- List info;
- List behavioursInfo;
- NetworkIdentity identity;
GUIContent title;
Styles styles = new Styles();
- public override void Initialize(UnityObject[] targets)
- {
- base.Initialize(targets);
- GetNetworkInformation(target as GameObject);
- }
-
public override GUIContent GetPreviewTitle()
{
if (title == null)
@@ -83,7 +73,8 @@ public override GUIContent GetPreviewTitle()
public override bool HasPreviewGUI()
{
- return info != null && info.Count > 0;
+ // need to check if target is null to stop MissingReferenceException
+ return target != null && target is GameObject gameObject && gameObject.GetComponent() != null;
}
public override void OnPreviewGUI(Rect r, GUIStyle background)
@@ -91,29 +82,53 @@ public override void OnPreviewGUI(Rect r, GUIStyle background)
if (Event.current.type != EventType.Repaint)
return;
- if (info == null || info.Count == 0)
+ if (target == null)
+ return;
+
+ GameObject targetGameObject = target as GameObject;
+
+ if (targetGameObject == null)
+ return;
+
+ NetworkIdentity identity = targetGameObject.GetComponent();
+
+ if (identity == null)
return;
if (styles == null)
styles = new Styles();
- // Get required label size for the names of the information values we're going to show
- // There are two columns, one with label for the name of the info and the next for the value
- Vector2 maxNameLabelSize = new Vector2(140, 16);
- Vector2 maxValueLabelSize = GetMaxNameLabelSize();
- //Apply padding
+ // padding
RectOffset previewPadding = new RectOffset(-5, -5, -5, -5);
Rect paddedr = previewPadding.Add(r);
//Centering
float initialX = paddedr.x + 10;
- float initialY = paddedr.y + 10;
+ float Y = paddedr.y + 10;
+
+ Y = DrawNetworkIdentityInfo(identity, initialX, Y);
+
+ Y = DrawNetworkBehaviors(identity, initialX, Y);
+
+ Y = DrawObservers(identity, initialX, Y);
- Rect labelRect = new Rect(initialX, initialY, maxNameLabelSize.x, maxNameLabelSize.y);
- Rect idLabelRect = new Rect(maxNameLabelSize.x, initialY, maxValueLabelSize.x, maxValueLabelSize.y);
+ _ = DrawOwner(identity, initialX, Y);
- foreach (NetworkIdentityInfo info in info)
+ }
+
+ float DrawNetworkIdentityInfo(NetworkIdentity identity, float initialX, float Y)
+ {
+ IEnumerable infos = GetNetworkIdentityInfo(identity);
+ // Get required label size for the names of the information values we're going to show
+ // There are two columns, one with label for the name of the info and the next for the value
+ Vector2 maxNameLabelSize = new Vector2(140, 16);
+ Vector2 maxValueLabelSize = GetMaxNameLabelSize(infos);
+
+ Rect labelRect = new Rect(initialX, Y, maxNameLabelSize.x, maxNameLabelSize.y);
+ Rect idLabelRect = new Rect(maxNameLabelSize.x, Y, maxValueLabelSize.x, maxValueLabelSize.y);
+
+ foreach (NetworkIdentityInfo info in infos)
{
GUI.Label(labelRect, info.name, styles.labelStyle);
GUI.Label(idLabelRect, info.value, styles.componentName);
@@ -122,59 +137,76 @@ public override void OnPreviewGUI(Rect r, GUIStyle background)
idLabelRect.y += idLabelRect.height;
}
+ return labelRect.y;
+ }
+
+ float DrawNetworkBehaviors(NetworkIdentity identity, float initialX, float Y)
+ {
+ IEnumerable behavioursInfo = GetNetworkBehaviorInfo(identity);
+
// Show behaviours list in a different way than the name/value pairs above
- float lastY = labelRect.y;
- if (behavioursInfo != null && behavioursInfo.Count > 0)
- {
- Vector2 maxBehaviourLabelSize = GetMaxBehaviourLabelSize();
- Rect behaviourRect = new Rect(initialX, labelRect.y + 10, maxBehaviourLabelSize.x, maxBehaviourLabelSize.y);
+ Vector2 maxBehaviourLabelSize = GetMaxBehaviourLabelSize(behavioursInfo);
+ Rect behaviourRect = new Rect(initialX, Y + 10, maxBehaviourLabelSize.x, maxBehaviourLabelSize.y);
- GUI.Label(behaviourRect, new GUIContent("Network Behaviours"), styles.labelStyle);
- behaviourRect.x += 20; // indent names
- behaviourRect.y += behaviourRect.height;
+ GUI.Label(behaviourRect, new GUIContent("Network Behaviours"), styles.labelStyle);
+ // indent names
+ behaviourRect.x += 20;
+ behaviourRect.y += behaviourRect.height;
- foreach (NetworkBehaviourInfo info in behavioursInfo)
+ foreach (NetworkBehaviourInfo info in behavioursInfo)
+ {
+ if (info.behaviour == null)
{
- if (info.behaviour == null)
- {
- // could be the case in the editor after existing play mode.
- continue;
- }
-
- GUI.Label(behaviourRect, info.name, info.behaviour.enabled ? styles.componentName : styles.disabledName);
- behaviourRect.y += behaviourRect.height;
- lastY = behaviourRect.y;
+ // could be the case in the editor after existing play mode.
+ continue;
}
- if (identity.observers != null && identity.observers.Count > 0)
- {
- Rect observerRect = new Rect(initialX, lastY + 10, 200, 20);
+ GUI.Label(behaviourRect, info.name, info.behaviour.enabled ? styles.componentName : styles.disabledName);
+ behaviourRect.y += behaviourRect.height;
+ Y = behaviourRect.y;
+ }
- GUI.Label(observerRect, new GUIContent("Network observers"), styles.labelStyle);
- observerRect.x += 20; // indent names
- observerRect.y += observerRect.height;
+ return Y;
+ }
- foreach (KeyValuePair kvp in identity.observers)
- {
- GUI.Label(observerRect, kvp.Value.address + ":" + kvp.Value.connectionId, styles.componentName);
- observerRect.y += observerRect.height;
- lastY = observerRect.y;
- }
- }
+ float DrawObservers(NetworkIdentity identity, float initialX, float Y)
+ {
+ if (identity.observers != null && identity.observers.Count > 0)
+ {
+ Rect observerRect = new Rect(initialX, Y + 10, 200, 20);
- if (identity.clientAuthorityOwner != null)
+ GUI.Label(observerRect, new GUIContent("Network observers"), styles.labelStyle);
+ // indent names
+ observerRect.x += 20;
+ observerRect.y += observerRect.height;
+
+ foreach (KeyValuePair kvp in identity.observers)
{
- Rect ownerRect = new Rect(initialX, lastY + 10, 400, 20);
- GUI.Label(ownerRect, new GUIContent("Client Authority: " + identity.clientAuthorityOwner), styles.labelStyle);
+ GUI.Label(observerRect, kvp.Value.address + ":" + kvp.Value, styles.componentName);
+ observerRect.y += observerRect.height;
+ Y = observerRect.y;
}
}
+
+ return Y;
+ }
+
+ float DrawOwner(NetworkIdentity identity, float initialX, float Y)
+ {
+ if (identity.connectionToClient != null)
+ {
+ Rect ownerRect = new Rect(initialX, Y + 10, 400, 20);
+ GUI.Label(ownerRect, new GUIContent("Client Authority: " + identity.connectionToClient), styles.labelStyle);
+ Y += ownerRect.height;
+ }
+ return Y;
}
// Get the maximum size used by the value of information items
- Vector2 GetMaxNameLabelSize()
+ Vector2 GetMaxNameLabelSize(IEnumerable infos)
{
Vector2 maxLabelSize = Vector2.zero;
- foreach (NetworkIdentityInfo info in info)
+ foreach (NetworkIdentityInfo info in infos)
{
Vector2 labelSize = styles.labelStyle.CalcSize(info.value);
if (maxLabelSize.x < labelSize.x)
@@ -189,7 +221,7 @@ Vector2 GetMaxNameLabelSize()
return maxLabelSize;
}
- Vector2 GetMaxBehaviourLabelSize()
+ Vector2 GetMaxBehaviourLabelSize(IEnumerable behavioursInfo)
{
Vector2 maxLabelSize = Vector2.zero;
foreach (NetworkBehaviourInfo behaviour in behavioursInfo)
@@ -207,47 +239,42 @@ Vector2 GetMaxBehaviourLabelSize()
return maxLabelSize;
}
- void GetNetworkInformation(GameObject gameObject)
+ IEnumerable GetNetworkIdentityInfo(NetworkIdentity identity)
{
- identity = gameObject.GetComponent();
- if (identity != null)
+ List infos = new List
{
- info = new List
- {
- GetAssetId(),
- GetString("Scene ID", identity.sceneId.ToString("X"))
- };
-
- if (!Application.isPlaying)
- {
- return;
- }
+ GetAssetId(identity),
+ GetString("Scene ID", identity.sceneId.ToString("X"))
+ };
- info.Add(GetString("Network ID", identity.netId.ToString()));
+ if (Application.isPlaying)
+ {
+ infos.Add(GetString("Network ID", identity.netId.ToString()));
+ infos.Add(GetBoolean("Is Client", identity.isClient));
+ infos.Add(GetBoolean("Is Server", identity.isServer));
+ infos.Add(GetBoolean("Has Authority", identity.hasAuthority));
+ infos.Add(GetBoolean("Is Local Player", identity.isLocalPlayer));
+ }
+ return infos;
+ }
- info.Add(GetBoolean("Is Client", identity.isClient));
- info.Add(GetBoolean("Is Server", identity.isServer));
- info.Add(GetBoolean("Has Authority", identity.hasAuthority));
- info.Add(GetBoolean("Is Local Player", identity.isLocalPlayer));
+ IEnumerable GetNetworkBehaviorInfo(NetworkIdentity identity)
+ {
+ List behaviourInfos = new List();
- NetworkBehaviour[] behaviours = gameObject.GetComponents();
- if (behaviours.Length > 0)
+ NetworkBehaviour[] behaviours = identity.GetComponents();
+ foreach (NetworkBehaviour behaviour in behaviours)
+ {
+ behaviourInfos.Add(new NetworkBehaviourInfo
{
- behavioursInfo = new List();
- foreach (NetworkBehaviour behaviour in behaviours)
- {
- NetworkBehaviourInfo info = new NetworkBehaviourInfo
- {
- name = new GUIContent(behaviour.GetType().FullName),
- behaviour = behaviour
- };
- behavioursInfo.Add(info);
- }
- }
+ name = new GUIContent(behaviour.GetType().FullName),
+ behaviour = behaviour
+ });
}
+ return behaviourInfos;
}
- NetworkIdentityInfo GetAssetId()
+ NetworkIdentityInfo GetAssetId(NetworkIdentity identity)
{
string assetId = identity.assetId.ToString();
if (string.IsNullOrEmpty(assetId))
@@ -259,22 +286,20 @@ NetworkIdentityInfo GetAssetId()
static NetworkIdentityInfo GetString(string name, string value)
{
- NetworkIdentityInfo info = new NetworkIdentityInfo
+ return new NetworkIdentityInfo
{
name = new GUIContent(name),
value = new GUIContent(value)
};
- return info;
}
static NetworkIdentityInfo GetBoolean(string name, bool value)
{
- NetworkIdentityInfo info = new NetworkIdentityInfo
+ return new NetworkIdentityInfo
{
name = new GUIContent(name),
value = new GUIContent((value ? "Yes" : "No"))
};
- return info;
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkManagerEditor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkManagerEditor.cs
index 0552cfa..315db46 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkManagerEditor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkManagerEditor.cs
@@ -31,7 +31,8 @@ protected void Init()
onRemoveCallback = RemoveButton,
onChangedCallback = Changed,
onAddCallback = AddButton,
- elementHeight = 16 // this uses a 16x16 icon. other sizes make it stretch.
+ // this uses a 16x16 icon. other sizes make it stretch.
+ elementHeight = 16
};
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkScenePostProcess.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkScenePostProcess.cs
index 866a50b..cb66328 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkScenePostProcess.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/NetworkScenePostProcess.cs
@@ -50,35 +50,7 @@ public static void OnPostProcessScene()
// (and only do SetActive if this was actually a scene object)
if (identity.sceneId != 0)
{
- // set scene hash
- identity.SetSceneIdSceneHashPartInternal();
-
- // disable it
- // note: NetworkIdentity.OnDisable adds itself to the
- // spawnableObjects dictionary (only if sceneId != 0)
- identity.gameObject.SetActive(false);
-
- // safety check for prefabs with more than one NetworkIdentity
- #if UNITY_2018_2_OR_NEWER
- GameObject prefabGO = PrefabUtility.GetCorrespondingObjectFromSource(identity.gameObject) as GameObject;
- #else
- GameObject prefabGO = PrefabUtility.GetPrefabParent(identity.gameObject) as GameObject;
- #endif
- if (prefabGO)
- {
- #if UNITY_2018_3_OR_NEWER
- GameObject prefabRootGO = prefabGO.transform.root.gameObject;
- #else
- GameObject prefabRootGO = PrefabUtility.FindPrefabRoot(prefabGO);
- #endif
- if (prefabRootGO)
- {
- if (prefabRootGO.GetComponentsInChildren().Length > 1)
- {
- Debug.LogWarningFormat("Prefab '{0}' has several NetworkIdentity components attached to itself or its children, this is not supported.", prefabRootGO.name);
- }
- }
- }
+ PrepareSceneObject(identity);
}
// throwing an exception would only show it for one object
// because this function would return afterwards.
@@ -86,5 +58,35 @@ public static void OnPostProcessScene()
}
}
}
+
+ static void PrepareSceneObject(NetworkIdentity identity)
+ {
+ // set scene hash
+ identity.SetSceneIdSceneHashPartInternal();
+
+ // disable it
+ // note: NetworkIdentity.OnDisable adds itself to the
+ // spawnableObjects dictionary (only if sceneId != 0)
+ identity.gameObject.SetActive(false);
+
+ // safety check for prefabs with more than one NetworkIdentity
+#if UNITY_2018_2_OR_NEWER
+ GameObject prefabGO = PrefabUtility.GetCorrespondingObjectFromSource(identity.gameObject);
+#else
+ GameObject prefabGO = PrefabUtility.GetPrefabParent(identity.gameObject);
+#endif
+ if (prefabGO)
+ {
+#if UNITY_2018_3_OR_NEWER
+ GameObject prefabRootGO = prefabGO.transform.root.gameObject;
+#else
+ GameObject prefabRootGO = PrefabUtility.FindPrefabRoot(prefabGO);
+#endif
+ if (prefabRootGO != null && prefabRootGO.GetComponentsInChildren().Length > 1)
+ {
+ Debug.LogWarningFormat("Prefab '{0}' has several NetworkIdentity components attached to itself or its children, this is not supported.", prefabRootGO.name);
+ }
+ }
+ }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/PreprocessorDefine.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/PreprocessorDefine.cs
deleted file mode 100644
index 9e23e33..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/PreprocessorDefine.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System.Collections.Generic;
-using UnityEditor;
-
-namespace Mirror
-{
- static class PreprocessorDefine
- {
- ///
- /// Add define symbols as soon as Unity gets done compiling.
- ///
- [InitializeOnLoadMethod]
- static void AddDefineSymbols()
- {
- HashSet defines = new HashSet(PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup).Split(';'))
- {
- "MIRROR",
- "MIRROR_1726_OR_NEWER",
- "MIRROR_3_0_OR_NEWER",
- "MIRROR_3_12_OR_NEWER",
- "MIRROR_4_0_OR_NEWER"
- };
- PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, string.Join(";", defines));
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/SceneDrawer.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/SceneDrawer.cs
index b6c04f4..a234c3f 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/SceneDrawer.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/SceneDrawer.cs
@@ -3,53 +3,44 @@
namespace Mirror
{
-
[CustomPropertyDrawer(typeof(SceneAttribute))]
public class SceneDrawer : PropertyDrawer
{
-
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
-
if (property.propertyType == SerializedPropertyType.String)
{
- SceneAsset sceneObject = GetSceneObject(property.stringValue);
- SceneAsset scene = (SceneAsset)EditorGUI.ObjectField(position, label, sceneObject, typeof(SceneAsset), true);
- if (scene == null)
+ SceneAsset sceneObject = AssetDatabase.LoadAssetAtPath(property.stringValue);
+
+ if (sceneObject == null && !string.IsNullOrEmpty(property.stringValue))
{
- property.stringValue = "";
+ // try to load it from the build settings for legacy compatibility
+ sceneObject = GetBuildSettingsSceneObject(property.stringValue);
}
- else if (scene.name != property.stringValue)
+ if (sceneObject == null && !string.IsNullOrEmpty(property.stringValue))
{
- SceneAsset sceneObj = GetSceneObject(scene.name);
- if (sceneObj == null)
- {
- Debug.LogWarning("The scene " + scene.name + " cannot be used. To use this scene add it to the build settings for the project");
- }
- else
- {
- property.stringValue = scene.name;
- }
+ Debug.LogError($"Could not find scene {property.stringValue} in {property.propertyPath}, assign the proper scenes in your NetworkManager");
}
+ SceneAsset scene = (SceneAsset)EditorGUI.ObjectField(position, label, sceneObject, typeof(SceneAsset), true);
+
+ property.stringValue = AssetDatabase.GetAssetPath(scene);
}
else
- EditorGUI.LabelField(position, label.text, "Use [Scene] with strings.");
- }
- protected SceneAsset GetSceneObject(string sceneObjectName)
- {
- if (string.IsNullOrEmpty(sceneObjectName))
{
- return null;
+ EditorGUI.LabelField(position, label.text, "Use [Scene] with strings.");
}
+ }
- foreach (EditorBuildSettingsScene editorScene in EditorBuildSettings.scenes)
+ protected SceneAsset GetBuildSettingsSceneObject(string sceneName)
+ {
+ foreach (EditorBuildSettingsScene buildScene in EditorBuildSettings.scenes)
{
- if (editorScene.path.IndexOf(sceneObjectName) != -1)
+ SceneAsset sceneAsset = AssetDatabase.LoadAssetAtPath(buildScene.path);
+ if (sceneAsset.name == sceneName)
{
- return AssetDatabase.LoadAssetAtPath(editorScene.path, typeof(SceneAsset)) as SceneAsset;
+ return sceneAsset;
}
}
- Debug.LogWarning("Scene [" + sceneObjectName + "] cannot be used. Add this scene to the 'Scenes in the Build' in build settings.");
return null;
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/ScriptableObjectUtility.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/ScriptableObjectUtility.cs
new file mode 100644
index 0000000..e6a36bd
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/ScriptableObjectUtility.cs
@@ -0,0 +1,54 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace Mirror.EditorScripts
+{
+ public static class ScriptableObjectUtility
+ {
+ ///
+ // This makes it easy to create, name and place unique new ScriptableObject asset files.
+ ///
+ public static T CreateAsset(string defaultName) where T : ScriptableObject
+ {
+ string path = SavePanel(defaultName);
+ // user click cancel
+ if (string.IsNullOrEmpty(path)) { return null; }
+
+ T asset = ScriptableObject.CreateInstance();
+
+ SaveAsset(path, asset);
+
+ return asset;
+ }
+
+ static string SavePanel(string name)
+ {
+ string path = EditorUtility.SaveFilePanel(
+ "Save ScriptableObject",
+ "Assets/Mirror/",
+ name + ".asset",
+ "asset");
+
+ // user click cancel, return early
+ if (string.IsNullOrEmpty(path)) { return path; }
+
+ // Unity only wants path from Assets
+ if (path.StartsWith(Application.dataPath))
+ {
+ path = "Assets" + path.Substring(Application.dataPath.Length);
+ }
+
+ return path;
+ }
+
+ static void SaveAsset(string path, ScriptableObject asset)
+ {
+ string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path);
+
+ AssetDatabase.CreateAsset(asset, assetPathAndName);
+
+ AssetDatabase.SaveAssets();
+ AssetDatabase.Refresh();
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/ScriptableObjectUtility.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/ScriptableObjectUtility.cs.meta
new file mode 100644
index 0000000..a1a0af3
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/ScriptableObjectUtility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4d54a29ddd5b52b4eaa07ed39c0e3e83
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/SyncVarAttributeDrawer.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/SyncVarAttributeDrawer.cs
new file mode 100644
index 0000000..f7b018a
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/SyncVarAttributeDrawer.cs
@@ -0,0 +1,28 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace Mirror
+{
+ [CustomPropertyDrawer(typeof(SyncVarAttribute))]
+ public class SyncVarAttributeDrawer : PropertyDrawer
+ {
+ static readonly GUIContent syncVarIndicatorContent = new GUIContent("SyncVar", "This variable has been marked with the [SyncVar] attribute.");
+
+ public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+ {
+ Vector2 syncVarIndicatorRect = EditorStyles.miniLabel.CalcSize(syncVarIndicatorContent);
+ float valueWidth = position.width - syncVarIndicatorRect.x;
+
+ Rect valueRect = new Rect(position.x, position.y, valueWidth, position.height);
+ Rect labelRect = new Rect(position.x + valueWidth, position.y, syncVarIndicatorRect.x, position.height);
+
+ EditorGUI.PropertyField(valueRect, property, true);
+ GUI.Label(labelRect, syncVarIndicatorContent, EditorStyles.miniLabel);
+ }
+
+ public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
+ {
+ return EditorGUI.GetPropertyHeight(property);
+ }
+ }
+} //namespace
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/SyncVarAttributeDrawer.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/SyncVarAttributeDrawer.cs.meta
new file mode 100644
index 0000000..6311f1d
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/SyncVarAttributeDrawer.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 27821afc81c4d064d8348fbeb00c0ce8
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/AssemblyInfo.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/AssemblyInfo.cs
new file mode 100644
index 0000000..08b43f5
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/AssemblyInfo.cs
@@ -0,0 +1,3 @@
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("Mirror.Tests")]
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/AssemblyInfo.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/AssemblyInfo.cs.meta
new file mode 100644
index 0000000..d356af8
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/AssemblyInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 929924d95663264478d4238d4910d22e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/CompilationFinishedHook.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/CompilationFinishedHook.cs
index b80db07..d15653b 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/CompilationFinishedHook.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/CompilationFinishedHook.cs
@@ -14,20 +14,21 @@ public static class CompilationFinishedHook
const string MirrorRuntimeAssemblyName = "Mirror";
const string MirrorWeaverAssemblyName = "Mirror.Weaver";
- public static Action OnWeaverMessage; // delegate for subscription to Weaver debug messages
- public static Action OnWeaverWarning; // delegate for subscription to Weaver warning messages
- public static Action OnWeaverError; // delete for subscription to Weaver error messages
-
- public static bool WeaverEnabled { get; set; } // controls whether we weave any assemblies when CompilationPipeline delegates are invoked
- public static bool UnityLogEnabled = true; // controls weather Weaver errors are reported direct to the Unity console (tests enable this)
- public static bool WeaveFailed { get; private set; } // holds the result status of our latest Weave operation
-
- // debug message handler that also calls OnMessageMethod delegate
- static void HandleMessage(string msg)
- {
- if (UnityLogEnabled) Debug.Log(msg);
- if (OnWeaverMessage != null) OnWeaverMessage.Invoke(msg);
- }
+ // delegate for subscription to Weaver debug messages
+ public static Action OnWeaverMessage;
+ // delegate for subscription to Weaver warning messages
+ public static Action OnWeaverWarning;
+ // delete for subscription to Weaver error messages
+ public static Action OnWeaverError;
+
+ // controls whether we weave any assemblies when CompilationPipeline delegates are invoked
+ public static bool WeaverEnabled { get; set; }
+ // controls weather Weaver errors are reported direct to the Unity console (tests enable this)
+ public static bool UnityLogEnabled = true;
+
+ // holds the result status of our latest Weave operation
+ // NOTE: WeaveFailed is critical to unit tests, but isn't used for anything else.
+ public static bool WeaveFailed { get; private set; }
// warning message handler that also calls OnWarningMethod delegate
static void HandleWarning(string msg)
@@ -44,20 +45,23 @@ static void HandleError(string msg)
}
[InitializeOnLoadMethod]
- static void OnInitializeOnLoad()
+ public static void OnInitializeOnLoad()
{
CompilationPipeline.assemblyCompilationFinished += OnCompilationFinished;
// We only need to run this once per session
// after that, all assemblies will be weaved by the event
- if (!SessionState.GetBool("MIRROR_WEAVED", false) )
+ if (!SessionState.GetBool("MIRROR_WEAVED", false))
{
+ // reset session flag
SessionState.SetBool("MIRROR_WEAVED", true);
- WeaveExisingAssemblies();
+ SessionState.SetBool("MIRROR_WEAVE_SUCCESS", true);
+
+ WeaveExistingAssemblies();
}
}
- static void WeaveExisingAssemblies()
+ public static void WeaveExistingAssemblies()
{
foreach (UnityAssembly assembly in CompilationPipeline.GetAssemblies())
{
@@ -67,7 +71,11 @@ static void WeaveExisingAssemblies()
}
}
+#if UNITY_2019_3_OR_NEWER
+ EditorUtility.RequestScriptReload();
+#else
UnityEditorInternal.InternalEditorUtility.RequestScriptReload();
+#endif
}
static string FindMirrorRuntime()
@@ -133,12 +141,33 @@ static void OnCompilationFinished(string assemblyPath, CompilerMessage[] message
return;
}
+ HashSet dependencyPaths = GetDependecyPaths(assemblyPath);
+
+ // passing null in the outputDirectory param will do an in-place update of the assembly
+ if (Program.Process(unityEngineCoreModuleDLL, mirrorRuntimeDll, null, new[] { assemblyPath }, dependencyPaths.ToArray(), HandleWarning, HandleError))
+ {
+ // NOTE: WeaveFailed is critical for unit tests but isn't used elsewhere
+ WeaveFailed = false;
+ }
+ else
+ {
+ // Set false...will be checked in \Editor\EnterPlayModeSettingsCheck.CheckSuccessfulWeave()
+ SessionState.SetBool("MIRROR_WEAVE_SUCCESS", false);
+
+ WeaveFailed = true;
+ if (UnityLogEnabled) Debug.LogError("Weaving failed for: " + assemblyPath);
+ }
+ }
+
+ static HashSet GetDependecyPaths(string assemblyPath)
+ {
// build directory list for later asm/symbol resolving using CompilationPipeline refs
HashSet dependencyPaths = new HashSet();
dependencyPaths.Add(Path.GetDirectoryName(assemblyPath));
foreach (UnityAssembly unityAsm in CompilationPipeline.GetAssemblies())
{
- if (unityAsm.outputPath != assemblyPath) continue;
+ if (unityAsm.outputPath != assemblyPath)
+ continue;
foreach (string unityAsmRef in unityAsm.compiledAssemblyReferences)
{
@@ -146,17 +175,7 @@ static void OnCompilationFinished(string assemblyPath, CompilerMessage[] message
}
}
- // passing null in the outputDirectory param will do an in-place update of the assembly
- if (Program.Process(unityEngineCoreModuleDLL, mirrorRuntimeDll, null, new[] { assemblyPath }, dependencyPaths.ToArray(), HandleWarning, HandleError))
- {
- WeaveFailed = false;
- //Debug.Log("Weaving succeeded for: " + assemblyPath);
- }
- else
- {
- WeaveFailed = true;
- if (UnityLogEnabled) Debug.LogError("Weaving failed for: " + assemblyPath);
- }
+ return dependencyPaths;
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Extensions.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Extensions.cs
index f2fad51..0d211bc 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Extensions.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Extensions.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using Mono.CecilX;
namespace Mirror.Weaver
@@ -6,6 +7,11 @@ namespace Mirror.Weaver
public static class Extensions
{
public static bool IsDerivedFrom(this TypeDefinition td, TypeReference baseClass)
+ {
+ return IsDerivedFrom(td, baseClass.FullName);
+ }
+
+ public static bool IsDerivedFrom(this TypeDefinition td, string baseClassFullName)
{
if (!td.IsClass)
return false;
@@ -23,7 +29,7 @@ public static bool IsDerivedFrom(this TypeDefinition td, TypeReference baseClass
parentName = parentName.Substring(0, index);
}
- if (parentName == baseClass.FullName)
+ if (parentName == baseClassFullName)
{
return true;
}
@@ -80,8 +86,10 @@ public static bool ImplementsInterface(this TypeDefinition td, TypeReference bas
public static bool IsArrayType(this TypeReference tr)
{
- if ((tr.IsArray && ((ArrayType)tr).ElementType.IsArray) || // jagged array
- (tr.IsArray && ((ArrayType)tr).Rank > 1)) // multidimensional array
+ // jagged array
+ if ((tr.IsArray && ((ArrayType)tr).ElementType.IsArray) ||
+ // multidimensional array
+ (tr.IsArray && ((ArrayType)tr).Rank > 1))
return false;
return true;
}
@@ -114,13 +122,12 @@ public static bool CanBeResolved(this TypeReference parent)
}
- // Given a method of a generic class such as ArraySegment.get_Count,
+ // Given a method of a generic class such as ArraySegment.get_Count,
// and a generic instance such as ArraySegment
- // Creates a reference to the specialized method ArraySegment.get_Count;
+ // Creates a reference to the specialized method ArraySegment.get_Count
// Note that calling ArraySegment.get_Count directly gives an invalid IL error
public static MethodReference MakeHostInstanceGeneric(this MethodReference self, GenericInstanceType instanceType)
{
-
MethodReference reference = new MethodReference(self.Name, self.ReturnType, instanceType)
{
CallingConvention = self.CallingConvention,
@@ -137,7 +144,7 @@ public static MethodReference MakeHostInstanceGeneric(this MethodReference self,
return Weaver.CurrentAssembly.MainModule.ImportReference(reference);
}
- public static CustomAttribute GetCustomAttribute(this MethodDefinition method, string attributeName)
+ public static CustomAttribute GetCustomAttribute(this ICustomAttributeProvider method, string attributeName)
{
foreach (CustomAttribute ca in method.CustomAttributes)
{
@@ -147,5 +154,171 @@ public static CustomAttribute GetCustomAttribute(this MethodDefinition method, s
return null;
}
+ public static CustomAttribute GetCustomAttribute(this ICustomAttributeProvider method, TypeReference attribute)
+ {
+ foreach (CustomAttribute ca in method.CustomAttributes)
+ {
+ if (ca.AttributeType.FullName == attribute.FullName)
+ return ca;
+ }
+ return null;
+ }
+
+ public static bool HasCustomAttribute(this ICustomAttributeProvider attributeProvider, string attributeName)
+ {
+ foreach (CustomAttribute ca in attributeProvider.CustomAttributes)
+ {
+ if (ca.AttributeType.FullName == attributeName)
+ return true;
+ }
+ return false;
+ }
+
+ public static bool HasCustomAttribute(this ICustomAttributeProvider attributeProvider, TypeReference attribute)
+ {
+ foreach (CustomAttribute ca in attributeProvider.CustomAttributes)
+ {
+ if (ca.AttributeType.FullName == attribute.FullName)
+ return true;
+ }
+ return false;
+ }
+
+ public static T GetField(this CustomAttribute ca, string field, T defaultValue)
+ {
+ foreach (CustomAttributeNamedArgument customField in ca.Fields)
+ {
+ if (customField.Name == field)
+ {
+ return (T)customField.Argument.Value;
+ }
+ }
+
+ return defaultValue;
+ }
+
+ public static MethodDefinition GetMethod(this TypeDefinition td, string methodName)
+ {
+ foreach (MethodDefinition md in td.Methods)
+ {
+ if (md.Name == methodName)
+ return md;
+ }
+ return null;
+ }
+
+ public static List GetMethods(this TypeDefinition td, string methodName)
+ {
+ List methods = new List();
+ foreach (MethodDefinition md in td.Methods)
+ {
+ if (md.Name == methodName)
+ methods.Add(md);
+ }
+ return methods;
+ }
+
+ public static MethodDefinition GetMethodInBaseType(this TypeDefinition td, string methodName)
+ {
+ TypeDefinition typedef = td;
+ while (typedef != null)
+ {
+ foreach (MethodDefinition md in typedef.Methods)
+ {
+ if (md.Name == methodName)
+ return md;
+ }
+
+ try
+ {
+ TypeReference parent = typedef.BaseType;
+ typedef = parent?.Resolve();
+ }
+ catch (AssemblyResolutionException)
+ {
+ // this can happen for pluins.
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool HasMethodInBaseType(this TypeDefinition td, string methodName, TypeReference stopAt)
+ {
+ TypeDefinition typedef = td;
+ while (typedef != null)
+ {
+ if (typedef.FullName == stopAt.FullName)
+ break;
+
+ foreach (MethodDefinition md in typedef.Methods)
+ {
+ if (md.Name == methodName)
+ return true;
+ }
+
+ try
+ {
+ TypeReference parent = typedef.BaseType;
+ typedef = parent?.Resolve();
+ }
+ catch (AssemblyResolutionException)
+ {
+ // this can happen for pluins.
+ break;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// Finds public fields in type and base type
+ ///
+ ///
+ ///
+ public static IEnumerable FindAllPublicFields(this TypeReference variable)
+ {
+ return FindAllPublicFields(variable.Resolve());
+ }
+
+ ///
+ /// Finds public fields in type and base type
+ ///
+ ///
+ ///
+ public static IEnumerable FindAllPublicFields(this TypeDefinition typeDefinition)
+ {
+ while (typeDefinition != null)
+ {
+ foreach (FieldDefinition field in typeDefinition.Fields)
+ {
+ if (field.IsStatic || field.IsPrivate)
+ continue;
+
+ if (field.IsNotSerialized)
+ continue;
+
+ yield return field;
+ }
+
+ try
+ {
+ typeDefinition = typeDefinition.BaseType.Resolve();
+ }
+ catch
+ {
+ break;
+ }
+ }
+ }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Helpers.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Helpers.cs
index a776954..44398fd 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Helpers.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Helpers.cs
@@ -1,63 +1,19 @@
-using System;
-using System.Linq;
-using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
-using Mono.CecilX;
-using Mono.CecilX.Cil;
-using Mono.CecilX.Mdb;
-using Mono.CecilX.Pdb;
namespace Mirror.Weaver
{
- class Helpers
+ static class Helpers
{
// This code is taken from SerializationWeaver
- class AddSearchDirectoryHelper
- {
- delegate void AddSearchDirectoryDelegate(string directory);
- readonly AddSearchDirectoryDelegate _addSearchDirectory;
-
- public AddSearchDirectoryHelper(IAssemblyResolver assemblyResolver)
- {
- // reflection is used because IAssemblyResolver doesn't implement AddSearchDirectory but both DefaultAssemblyResolver and NuGetAssemblyResolver do
- MethodInfo addSearchDirectory = assemblyResolver.GetType().GetMethod("AddSearchDirectory", BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
- if (addSearchDirectory == null)
- throw new Exception("Assembly resolver doesn't implement AddSearchDirectory method.");
- _addSearchDirectory = (AddSearchDirectoryDelegate)Delegate.CreateDelegate(typeof(AddSearchDirectoryDelegate), assemblyResolver, addSearchDirectory);
- }
-
- public void AddSearchDirectory(string directory)
- {
- _addSearchDirectory(directory);
- }
- }
-
- public static string UnityEngineDLLDirectoryName()
+ public static string UnityEngineDllDirectoryName()
{
string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
return directoryName?.Replace(@"file:\", "");
}
- public static ISymbolReaderProvider GetSymbolReaderProvider(string inputFile)
- {
- string nakedFileName = inputFile.Substring(0, inputFile.Length - 4);
- if (File.Exists(nakedFileName + ".pdb"))
- {
- Console.WriteLine("Symbols will be read from " + nakedFileName + ".pdb");
- return new PdbReaderProvider();
- }
- if (File.Exists(nakedFileName + ".dll.mdb"))
- {
- Console.WriteLine("Symbols will be read from " + nakedFileName + ".dll.mdb");
- return new MdbReaderProvider();
- }
- Console.WriteLine("No symbols for " + inputFile);
- return null;
- }
-
public static string DestinationFileFor(string outputDir, string assemblyPath)
{
string fileName = Path.GetFileName(assemblyPath);
@@ -65,60 +21,5 @@ public static string DestinationFileFor(string outputDir, string assemblyPath)
return Path.Combine(outputDir, fileName);
}
-
- public static string PrettyPrintType(TypeReference type)
- {
- // generic instances, such as List
- if (type.IsGenericInstance)
- {
- GenericInstanceType giType = (GenericInstanceType)type;
- return giType.Name.Substring(0, giType.Name.Length - 2) + "<" + string.Join(", ", giType.GenericArguments.Select(PrettyPrintType).ToArray()) + ">";
- }
-
- // generic types, such as List
- if (type.HasGenericParameters)
- {
- return type.Name.Substring(0, type.Name.Length - 2) + "<" + string.Join(", ", type.GenericParameters.Select(x => x.Name).ToArray()) + ">";
- }
-
- // non-generic type such as Int
- return type.Name;
- }
-
- public static ReaderParameters ReaderParameters(string assemblyPath, IEnumerable extraPaths, IAssemblyResolver assemblyResolver, string unityEngineDLLPath, string mirrorNetDLLPath)
- {
- ReaderParameters parameters = new ReaderParameters {ReadWrite = true};
- if (assemblyResolver == null)
- assemblyResolver = new DefaultAssemblyResolver();
- AddSearchDirectoryHelper helper = new AddSearchDirectoryHelper(assemblyResolver);
- helper.AddSearchDirectory(Path.GetDirectoryName(assemblyPath));
- helper.AddSearchDirectory(UnityEngineDLLDirectoryName());
- helper.AddSearchDirectory(Path.GetDirectoryName(unityEngineDLLPath));
- helper.AddSearchDirectory(Path.GetDirectoryName(mirrorNetDLLPath));
- if (extraPaths != null)
- {
- foreach (string path in extraPaths)
- helper.AddSearchDirectory(path);
- }
- parameters.AssemblyResolver = assemblyResolver;
- parameters.SymbolReaderProvider = GetSymbolReaderProvider(assemblyPath);
- return parameters;
- }
-
- public static WriterParameters GetWriterParameters(ReaderParameters readParams)
- {
- WriterParameters writeParams = new WriterParameters();
- if (readParams.SymbolReaderProvider is PdbReaderProvider)
- {
- //Log("Will export symbols of pdb format");
- writeParams.SymbolWriterProvider = new PdbWriterProvider();
- }
- else if (readParams.SymbolReaderProvider is MdbReaderProvider)
- {
- //Log("Will export symbols of mdb format");
- writeParams.SymbolWriterProvider = new MdbWriterProvider();
- }
- return writeParams;
- }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/CommandProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/CommandProcessor.cs
index b230d34..3d8ca27 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/CommandProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/CommandProcessor.cs
@@ -1,24 +1,17 @@
-// all the [Command] code from NetworkBehaviourProcessor in one place
using Mono.CecilX;
using Mono.CecilX.Cil;
namespace Mirror.Weaver
{
+ ///
+ /// Processes [Command] methods in NetworkBehaviour
+ ///
public static class CommandProcessor
{
- const string CmdPrefix = "InvokeCmd";
-
/*
// generates code like:
public void CmdThrust(float thrusting, int spin)
{
- if (isServer)
- {
- // we are ON the server, invoke directly
- CmdThrust(thrusting, spin);
- return;
- }
-
NetworkWriter networkWriter = new NetworkWriter();
networkWriter.Write(thrusting);
networkWriter.WritePackedUInt32((uint)spin);
@@ -33,87 +26,53 @@ public void CallCmdThrust(float thrusting, int spin)
Originally HLAPI put the send message code inside the Call function
and then proceeded to replace every call to CmdTrust with CallCmdTrust
- This method moves all the user's code into the "Call" method
+ This method moves all the user's code into the "CallCmd" method
and replaces the body of the original method with the send message code.
This way we do not need to modify the code anywhere else, and this works
correctly in dependent assemblies
*/
- public static MethodDefinition ProcessCommandCall(TypeDefinition td, MethodDefinition md, CustomAttribute ca)
+ public static MethodDefinition ProcessCommandCall(TypeDefinition td, MethodDefinition md, CustomAttribute commandAttr)
{
- MethodDefinition cmd = new MethodDefinition("Call" + md.Name,
- MethodAttributes.Public | MethodAttributes.HideBySig,
- Weaver.voidType);
-
- // add parameters
- foreach (ParameterDefinition pd in md.Parameters)
- {
- cmd.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
- }
-
- // move the old body to the new function
- MethodBody newBody = cmd.Body;
- cmd.Body = md.Body;
- md.Body = newBody;
-
- ILProcessor cmdWorker = md.Body.GetILProcessor();
-
- NetworkBehaviourProcessor.WriteSetupLocals(cmdWorker);
-
- if (Weaver.GenerateLogErrors)
- {
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, "Call Command function " + md.Name));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.logErrorReference));
- }
+ MethodDefinition cmd = MethodProcessor.SubstituteMethod(td, md);
- // local client check
- Instruction localClientLabel = cmdWorker.Create(OpCodes.Nop);
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.getBehaviourIsServer));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Brfalse, localClientLabel));
+ ILProcessor worker = md.Body.GetILProcessor();
- // call the cmd function directly.
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0));
- for (int i = 0; i < md.Parameters.Count; i++)
- {
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg, i + 1));
- }
- cmdWorker.Append(cmdWorker.Create(OpCodes.Call, cmd));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ret));
- cmdWorker.Append(localClientLabel);
+ NetworkBehaviourProcessor.WriteSetupLocals(worker);
// NetworkWriter writer = new NetworkWriter();
- NetworkBehaviourProcessor.WriteCreateWriter(cmdWorker);
+ NetworkBehaviourProcessor.WriteCreateWriter(worker);
// write all the arguments that the user passed to the Cmd call
- if (!NetworkBehaviourProcessor.WriteArguments(cmdWorker, md, false))
+ if (!NetworkBehaviourProcessor.WriteArguments(worker, md, RemoteCallType.Command))
return null;
string cmdName = md.Name;
- int index = cmdName.IndexOf(CmdPrefix);
- if (index > -1)
- {
- cmdName = cmdName.Substring(CmdPrefix.Length);
- }
+ int channel = commandAttr.GetField("channel", 0);
+ bool ignoreAuthority = commandAttr.GetField("ignoreAuthority", false);
// invoke internal send and return
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); // load 'base.' to call the SendCommand function with
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldtoken, td));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); // invokerClass
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, cmdName));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldloc_0)); // writer
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.sendCommandInternal));
-
- NetworkBehaviourProcessor.WriteRecycleWriter(cmdWorker);
-
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ret));
+ // load 'base.' to call the SendCommand function with
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldtoken, td));
+ // invokerClass
+ worker.Append(worker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference));
+ worker.Append(worker.Create(OpCodes.Ldstr, cmdName));
+ // writer
+ worker.Append(worker.Create(OpCodes.Ldloc_0));
+ worker.Append(worker.Create(OpCodes.Ldc_I4, channel));
+ worker.Append(worker.Create(ignoreAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.sendCommandInternal));
+
+ NetworkBehaviourProcessor.WriteRecycleWriter(worker);
+
+ worker.Append(worker.Create(OpCodes.Ret));
return cmd;
}
/*
// generates code like:
- protected static void InvokeCmdCmdThrust(NetworkBehaviour obj, NetworkReader reader)
+ protected static void InvokeCmdCmdThrust(NetworkBehaviour obj, NetworkReader reader, NetworkConnection senderConnection)
{
if (!NetworkServer.active)
{
@@ -122,50 +81,60 @@ protected static void InvokeCmdCmdThrust(NetworkBehaviour obj, NetworkReader rea
((ShipControl)obj).CmdThrust(reader.ReadSingle(), (int)reader.ReadPackedUInt32());
}
*/
- public static MethodDefinition ProcessCommandInvoke(TypeDefinition td, MethodDefinition md, MethodDefinition cmdCallFunc)
+ public static MethodDefinition ProcessCommandInvoke(TypeDefinition td, MethodDefinition method, MethodDefinition cmdCallFunc)
{
- MethodDefinition cmd = new MethodDefinition(CmdPrefix + md.Name,
+ MethodDefinition cmd = new MethodDefinition(Weaver.InvokeRpcPrefix + method.Name,
MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig,
Weaver.voidType);
- ILProcessor cmdWorker = cmd.Body.GetILProcessor();
- Instruction label = cmdWorker.Create(OpCodes.Nop);
+ ILProcessor worker = cmd.Body.GetILProcessor();
+ Instruction label = worker.Create(OpCodes.Nop);
- NetworkBehaviourProcessor.WriteServerActiveCheck(cmdWorker, md.Name, label, "Command");
+ NetworkBehaviourProcessor.WriteServerActiveCheck(worker, method.Name, label, "Command");
// setup for reader
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Castclass, td));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Castclass, td));
- if (!NetworkBehaviourProcessor.ProcessNetworkReaderParameters(md, cmdWorker, false))
+ if (!NetworkBehaviourProcessor.ReadArguments(method, worker, RemoteCallType.Command))
return null;
+ AddSenderConnection(method, worker);
+
// invoke actual command function
- cmdWorker.Append(cmdWorker.Create(OpCodes.Callvirt, cmdCallFunc));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Callvirt, cmdCallFunc));
+ worker.Append(worker.Create(OpCodes.Ret));
NetworkBehaviourProcessor.AddInvokeParameters(cmd.Parameters);
+ td.Methods.Add(cmd);
return cmd;
}
- public static bool ProcessMethodsValidateCommand(MethodDefinition md, CustomAttribute ca)
+ static void AddSenderConnection(MethodDefinition method, ILProcessor worker)
{
- if (!md.Name.StartsWith("Cmd"))
+ foreach (ParameterDefinition param in method.Parameters)
{
- Weaver.Error($"{md} must start with Cmd. Consider renaming it to Cmd{md.Name}");
- return false;
+ if (NetworkBehaviourProcessor.IsSenderConnection(param, RemoteCallType.Command))
+ {
+ // NetworkConnection is 3nd arg (arg0 is "obj" not "this" because method is static)
+ // exmaple: static void InvokeCmdCmdSendCommand(NetworkBehaviour obj, NetworkReader reader, NetworkConnection connection)
+ worker.Append(worker.Create(OpCodes.Ldarg_2));
+ }
}
+ }
+ public static bool ProcessMethodsValidateCommand(MethodDefinition md)
+ {
if (md.IsStatic)
{
- Weaver.Error($"{md} cannot be static");
+ Weaver.Error($"{md.Name} cannot be static", md);
return false;
}
// validate
return NetworkBehaviourProcessor.ProcessMethodsValidateFunction(md) &&
- NetworkBehaviourProcessor.ProcessMethodsValidateParameters(md, ca);
+ NetworkBehaviourProcessor.ProcessMethodsValidateParameters(md, RemoteCallType.Command);
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/GenericArgumentResolver.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/GenericArgumentResolver.cs
new file mode 100644
index 0000000..7d15a64
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/GenericArgumentResolver.cs
@@ -0,0 +1,110 @@
+using System.Collections.Generic;
+using Mono.CecilX;
+
+namespace Mirror.Weaver
+{
+ public class GenericArgumentResolver
+ {
+ readonly Stack stack = new Stack();
+ readonly int maxGenericArgument;
+
+ public GenericArgumentResolver(int maxGenericArgument)
+ {
+ this.maxGenericArgument = maxGenericArgument;
+ }
+
+ public bool GetGenericFromBaseClass(TypeDefinition td, int genericArgument, TypeReference baseType, out TypeReference itemType)
+ {
+ itemType = null;
+ if (GetGenericBaseType(td, baseType, out GenericInstanceType parent))
+ {
+ TypeReference arg = parent.GenericArguments[genericArgument];
+ if (arg.IsGenericParameter)
+ {
+ itemType = FindParameterInStack(td, genericArgument);
+ }
+ else
+ {
+ itemType = Weaver.CurrentAssembly.MainModule.ImportReference(arg);
+ }
+ }
+
+ return itemType != null;
+ }
+
+ TypeReference FindParameterInStack(TypeDefinition td, int genericArgument)
+ {
+ while (stack.Count > 0)
+ {
+ TypeReference next = stack.Pop();
+
+ if (!(next is GenericInstanceType genericType))
+ {
+ // if type is not GenericInstanceType something has gone wrong
+ return null;
+ }
+
+ if (genericType.GenericArguments.Count < genericArgument)
+ {
+ // if less than `genericArgument` then we didnt find generic argument
+ return null;
+ }
+
+ if (genericType.GenericArguments.Count > maxGenericArgument)
+ {
+ // if greater than `genericArgument` it is hard to know which generic arg we want
+ // See SyncListGenericInheritanceWithMultipleGeneric test
+ Weaver.Error($"Type {td.Name} has too many generic arguments in base class {next}", td);
+ return null;
+ }
+
+ TypeReference genericArg = genericType.GenericArguments[genericArgument];
+ if (!genericArg.IsGenericParameter)
+ {
+ // if not generic, successfully found type
+ return Weaver.CurrentAssembly.MainModule.ImportReference(genericArg);
+ }
+ }
+
+ // nothing left in stack, something went wrong
+ return null;
+ }
+
+ bool GetGenericBaseType(TypeDefinition td, TypeReference baseType, out GenericInstanceType found)
+ {
+ stack.Clear();
+ TypeReference parent = td.BaseType;
+ found = null;
+
+ while (parent != null)
+ {
+ string parentName = parent.FullName;
+
+ // strip generic parameters
+ int index = parentName.IndexOf('<');
+ if (index != -1)
+ {
+ parentName = parentName.Substring(0, index);
+ }
+
+ if (parentName == baseType.FullName)
+ {
+ found = parent as GenericInstanceType;
+ break;
+ }
+ try
+ {
+ stack.Push(parent);
+ parent = parent.Resolve().BaseType;
+ }
+ catch (AssemblyResolutionException)
+ {
+ // this can happen for plugins.
+ break;
+ }
+ }
+
+ return found != null;
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/GenericArgumentResolver.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/GenericArgumentResolver.cs.meta
new file mode 100644
index 0000000..685f914
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/GenericArgumentResolver.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fd67b3f7c2d66074a9bc7a23787e2ffb
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MessageClassProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MessageClassProcessor.cs
index 131a6a5..f12e4b2 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MessageClassProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MessageClassProcessor.cs
@@ -1,11 +1,20 @@
-// this class generates OnSerialize/OnDeserialize when inheriting from MessageBase
+using System.Linq;
using Mono.CecilX;
using Mono.CecilX.Cil;
namespace Mirror.Weaver
{
+ ///
+ /// generates OnSerialize/OnDeserialize when inheriting from MessageBase
+ ///
static class MessageClassProcessor
{
+
+ static bool IsEmptyDefault(this MethodBody body)
+ {
+ return body.Instructions.All(instruction => instruction.OpCode == OpCodes.Nop || instruction.OpCode == OpCodes.Ret);
+ }
+
public static void Process(TypeDefinition td)
{
Weaver.DLog(td, "MessageClassProcessor Start");
@@ -23,10 +32,10 @@ public static void Process(TypeDefinition td)
static void GenerateSerialization(TypeDefinition td)
{
Weaver.DLog(td, " GenerateSerialization");
- foreach (MethodDefinition m in td.Methods)
+ MethodDefinition existingMethod = td.GetMethod("Serialize");
+ if (existingMethod != null && !existingMethod.Body.IsEmptyDefault())
{
- if (m.Name == "Serialize")
- return;
+ return;
}
if (td.Fields.Count == 0)
@@ -39,61 +48,86 @@ static void GenerateSerialization(TypeDefinition td)
{
if (field.FieldType.FullName == td.FullName)
{
- Weaver.Error($"{td} has field ${field} that references itself");
+ Weaver.Error($"{td.Name} has field {field.Name} that references itself", field);
return;
}
}
- MethodDefinition serializeFunc = new MethodDefinition("Serialize",
+ MethodDefinition serializeFunc = existingMethod ?? new MethodDefinition("Serialize",
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
Weaver.voidType);
- serializeFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkWriterType)));
- ILProcessor serWorker = serializeFunc.Body.GetILProcessor();
+ //only add to new method
+ if (existingMethod == null)
+ {
+ serializeFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkWriterType)));
+ }
+ ILProcessor worker = serializeFunc.Body.GetILProcessor();
+ if (existingMethod != null)
+ {
+ //remove default nop&ret from existing empty interface method
+ worker.Body.Instructions.Clear();
+ }
+
+ // if it is not a struct, call base
+ if (!td.IsValueType)
+ {
+ // call base
+ CallBase(td, worker, "Serialize");
+ }
foreach (FieldDefinition field in td.Fields)
{
if (field.IsStatic || field.IsPrivate || field.IsSpecialName)
continue;
- if (field.FieldType.Resolve().HasGenericParameters && !field.FieldType.FullName.StartsWith("System.ArraySegment`1", System.StringComparison.Ordinal))
- {
- Weaver.Error($"{field} cannot have generic type {field.FieldType}. Consider creating a class that derives the generic type");
- return;
- }
+ CallWriter(worker, field);
+ }
+ worker.Append(worker.Create(OpCodes.Ret));
- if (field.FieldType.Resolve().IsInterface)
- {
- Weaver.Error($"{field} has unsupported type. Use a concrete class instead of interface {field.FieldType}");
- return;
- }
+ //only add if not just replaced body
+ if (existingMethod == null)
+ {
+ td.Methods.Add(serializeFunc);
+ }
+ }
- MethodReference writeFunc = Writers.GetWriteFunc(field.FieldType);
- if (writeFunc != null)
- {
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
- serWorker.Append(serWorker.Create(OpCodes.Ldfld, field));
- serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
- }
- else
- {
- Weaver.Error($"{field} has unsupported type");
- return;
- }
+ static void CallWriter(ILProcessor worker, FieldDefinition field)
+ {
+ MethodReference writeFunc = Writers.GetWriteFunc(field.FieldType);
+ if (writeFunc != null)
+ {
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, field));
+ worker.Append(worker.Create(OpCodes.Call, writeFunc));
}
- serWorker.Append(serWorker.Create(OpCodes.Ret));
+ else
+ {
+ Weaver.Error($"{field.Name} has unsupported type", field);
+ }
+ }
- td.Methods.Add(serializeFunc);
+ static void CallBase(TypeDefinition td, ILProcessor worker, string name)
+ {
+ MethodReference method = Resolvers.TryResolveMethodInParents(td.BaseType, Weaver.CurrentAssembly, name);
+ if (method != null)
+ {
+ // base
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ // writer
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ worker.Append(worker.Create(OpCodes.Call, method));
+ }
}
static void GenerateDeSerialization(TypeDefinition td)
{
Weaver.DLog(td, " GenerateDeserialization");
- foreach (MethodDefinition m in td.Methods)
+ MethodDefinition existingMethod = td.GetMethod("Deserialize");
+ if (existingMethod != null && !existingMethod.Body.IsEmptyDefault())
{
- if (m.Name == "Deserialize")
- return;
+ return;
}
if (td.Fields.Count == 0)
@@ -101,35 +135,58 @@ static void GenerateDeSerialization(TypeDefinition td)
return;
}
- MethodDefinition serializeFunc = new MethodDefinition("Deserialize",
+ MethodDefinition serializeFunc = existingMethod ?? new MethodDefinition("Deserialize",
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
Weaver.voidType);
- serializeFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
- ILProcessor serWorker = serializeFunc.Body.GetILProcessor();
+ //only add to new method
+ if (existingMethod == null)
+ {
+ serializeFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
+ }
+ ILProcessor worker = serializeFunc.Body.GetILProcessor();
+ if (existingMethod != null)
+ {
+ //remove default nop&ret from existing empty interface method
+ worker.Body.Instructions.Clear();
+ }
+
+ // if not value type, call base
+ if (!td.IsValueType)
+ {
+ CallBase(td, worker, "Deserialize");
+ }
foreach (FieldDefinition field in td.Fields)
{
if (field.IsStatic || field.IsPrivate || field.IsSpecialName)
continue;
- MethodReference readerFunc = Readers.GetReadFunc(field.FieldType);
- if (readerFunc != null)
- {
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
- serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc));
- serWorker.Append(serWorker.Create(OpCodes.Stfld, field));
- }
- else
- {
- Weaver.Error($"{field} has unsupported type");
- return;
- }
+ CallReader(worker, field);
+ }
+ worker.Append(worker.Create(OpCodes.Ret));
+
+ //only add if not just replaced body
+ if (existingMethod == null)
+ {
+ td.Methods.Add(serializeFunc);
}
- serWorker.Append(serWorker.Create(OpCodes.Ret));
+ }
- td.Methods.Add(serializeFunc);
+ static void CallReader(ILProcessor worker, FieldDefinition field)
+ {
+ MethodReference readerFunc = Readers.GetReadFunc(field.FieldType);
+ if (readerFunc != null)
+ {
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ worker.Append(worker.Create(OpCodes.Call, readerFunc));
+ worker.Append(worker.Create(OpCodes.Stfld, field));
+ }
+ else
+ {
+ Weaver.Error($"{field.Name} has unsupported type", field);
+ }
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MethodProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MethodProcessor.cs
new file mode 100644
index 0000000..6ea5663
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MethodProcessor.cs
@@ -0,0 +1,125 @@
+using Mono.CecilX;
+using Mono.CecilX.Cil;
+
+namespace Mirror.Weaver
+{
+ public static class MethodProcessor
+ {
+ private const string RpcPrefix = "UserCode_";
+
+ // creates a method substitute
+ // For example, if we have this:
+ // public void CmdThrust(float thrusting, int spin)
+ // {
+ // xxxxx
+ // }
+ //
+ // it will substitute the method and move the code to a new method with a provided name
+ // for example:
+ //
+ // public void CmdTrust(float thrusting, int spin)
+ // {
+ // }
+ //
+ // public void (float thrusting, int spin)
+ // {
+ // xxxxx
+ // }
+ //
+ // Note that all the calls to the method remain untouched
+ //
+ // the original method definition loses all code
+ // this returns the newly created method with all the user provided code
+ public static MethodDefinition SubstituteMethod(TypeDefinition td, MethodDefinition md)
+ {
+ string newName = RpcPrefix + md.Name;
+ MethodDefinition cmd = new MethodDefinition(newName, md.Attributes, md.ReturnType);
+
+ // add parameters
+ foreach (ParameterDefinition pd in md.Parameters)
+ {
+ cmd.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
+ }
+
+ // swap bodies
+ (cmd.Body, md.Body) = (md.Body, cmd.Body);
+
+ // Move over all the debugging information
+ foreach (SequencePoint sequencePoint in md.DebugInformation.SequencePoints)
+ cmd.DebugInformation.SequencePoints.Add(sequencePoint);
+ md.DebugInformation.SequencePoints.Clear();
+
+ foreach (CustomDebugInformation customInfo in md.CustomDebugInformations)
+ cmd.CustomDebugInformations.Add(customInfo);
+ md.CustomDebugInformations.Clear();
+
+ (md.DebugInformation.Scope, cmd.DebugInformation.Scope) = (cmd.DebugInformation.Scope, md.DebugInformation.Scope);
+
+ td.Methods.Add(cmd);
+
+ FixRemoteCallToBaseMethod(td, cmd);
+ return cmd;
+ }
+
+ ///
+ /// Finds and fixes call to base methods within remote calls
+ /// For example, changes `base.CmdDoSomething` to `base.CallCmdDoSomething` within `this.CallCmdDoSomething`
+ ///
+ ///
+ ///
+ public static void FixRemoteCallToBaseMethod(TypeDefinition type, MethodDefinition method)
+ {
+ string callName = method.Name;
+
+ // Cmd/rpc start with Weaver.RpcPrefix
+ // eg CallCmdDoSomething
+ if (!callName.StartsWith(RpcPrefix))
+ return;
+
+ // eg CmdDoSomething
+ string baseRemoteCallName = method.Name.Substring(RpcPrefix.Length);
+
+ foreach (Instruction instruction in method.Body.Instructions)
+ {
+ // if call to base.CmdDoSomething within this.CallCmdDoSomething
+ if (IsCallToMethod(instruction, out MethodDefinition calledMethod) &&
+ calledMethod.Name == baseRemoteCallName)
+ {
+ TypeDefinition baseType = type.BaseType.Resolve();
+ MethodDefinition baseMethod = baseType.GetMethodInBaseType(callName);
+
+ if (baseMethod == null)
+ {
+ Weaver.Error($"Could not find base method for {callName}", method);
+ return;
+ }
+
+ if (!baseMethod.IsVirtual)
+ {
+ Weaver.Error($"Could not find base method that was virutal {callName}", method);
+ return;
+ }
+
+ instruction.Operand = baseMethod;
+
+ Weaver.DLog(type, "Replacing call to '{0}' with '{1}' inside '{2}'", calledMethod.FullName, baseMethod.FullName, method.FullName);
+ }
+ }
+ }
+
+ static bool IsCallToMethod(Instruction instruction, out MethodDefinition calledMethod)
+ {
+ if (instruction.OpCode == OpCodes.Call &&
+ instruction.Operand is MethodDefinition method)
+ {
+ calledMethod = method;
+ return true;
+ }
+ else
+ {
+ calledMethod = null;
+ return false;
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MethodProcessor.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MethodProcessor.cs.meta
new file mode 100644
index 0000000..3c81894
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MethodProcessor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 661e1af528e3441f79e1552fb5ec4e0e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MonoBehaviourProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MonoBehaviourProcessor.cs
index c5f880e..fafa89a 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MonoBehaviourProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/MonoBehaviourProcessor.cs
@@ -1,8 +1,10 @@
-// this class only shows warnings in case we use SyncVars etc. for MonoBehaviour.
using Mono.CecilX;
namespace Mirror.Weaver
{
+ ///
+ /// only shows warnings in case we use SyncVars etc. for MonoBehaviour.
+ ///
static class MonoBehaviourProcessor
{
public static void Process(TypeDefinition td)
@@ -16,17 +18,12 @@ static void ProcessSyncVars(TypeDefinition td)
// find syncvars
foreach (FieldDefinition fd in td.Fields)
{
- foreach (CustomAttribute ca in fd.CustomAttributes)
- {
- if (ca.AttributeType.FullName == Weaver.SyncVarType.FullName)
- {
- Weaver.Error($"[SyncVar] {fd} must be inside a NetworkBehaviour. {td} is not a NetworkBehaviour");
- }
- }
+ if (fd.HasCustomAttribute(Weaver.SyncVarType))
+ Weaver.Error($"SyncVar {fd.Name} must be inside a NetworkBehaviour. {td.Name} is not a NetworkBehaviour", fd);
if (SyncObjectInitializer.ImplementsSyncObject(fd.FieldType))
{
- Weaver.Error($"{fd} is a SyncObject and must be inside a NetworkBehaviour. {td} is not a NetworkBehaviour");
+ Weaver.Error($"{fd.Name} is a SyncObject and must be inside a NetworkBehaviour. {td.Name} is not a NetworkBehaviour", fd);
}
}
}
@@ -40,17 +37,17 @@ static void ProcessMethods(TypeDefinition td)
{
if (ca.AttributeType.FullName == Weaver.CommandType.FullName)
{
- Weaver.Error($"[Command] {md} must be declared inside a NetworkBehaviour");
+ Weaver.Error($"Command {md.Name} must be declared inside a NetworkBehaviour", md);
}
if (ca.AttributeType.FullName == Weaver.ClientRpcType.FullName)
{
- Weaver.Error($"[ClienRpc] {md} must be declared inside a NetworkBehaviour");
+ Weaver.Error($"ClientRpc {md.Name} must be declared inside a NetworkBehaviour", md);
}
if (ca.AttributeType.FullName == Weaver.TargetRpcType.FullName)
{
- Weaver.Error($"[TargetRpc] {md} must be declared inside a NetworkBehaviour");
+ Weaver.Error($"TargetRpc {md.Name} must be declared inside a NetworkBehaviour", md);
}
string attributeName = ca.Constructor.DeclaringType.ToString();
@@ -58,16 +55,16 @@ static void ProcessMethods(TypeDefinition td)
switch (attributeName)
{
case "Mirror.ServerAttribute":
- Weaver.Error($"[Server] {md} must be declared inside a NetworkBehaviour");
+ Weaver.Error($"Server method {md.Name} must be declared inside a NetworkBehaviour", md);
break;
case "Mirror.ServerCallbackAttribute":
- Weaver.Error($"[ServerCallback] {md} must be declared inside a NetworkBehaviour");
+ Weaver.Error($"ServerCallback method {md.Name} must be declared inside a NetworkBehaviour", md);
break;
case "Mirror.ClientAttribute":
- Weaver.Error($"[Client] {md} must be declared inside a NetworkBehaviour");
+ Weaver.Error($"Client method {md.Name} must be declared inside a NetworkBehaviour", md);
break;
case "Mirror.ClientCallbackAttribute":
- Weaver.Error($"[ClientCallback] {md} must be declared inside a NetworkBehaviour");
+ Weaver.Error($"ClientCallback method {md.Name} must be declared inside a NetworkBehaviour", md);
break;
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs
index 6c54025..038835f 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/NetworkBehaviourProcessor.cs
@@ -1,19 +1,29 @@
-// this class processes SyncVars, Cmds, Rpcs, etc. of NetworkBehaviours
-using System;
-using System.Linq;
using System.Collections.Generic;
using Mono.CecilX;
using Mono.CecilX.Cil;
namespace Mirror.Weaver
{
+ public enum RemoteCallType
+ {
+ Command,
+ ClientRpc,
+ TargetRpc,
+ SyncEvent
+ }
+
+
+ ///
+ /// processes SyncVars, Cmds, Rpcs, etc. of NetworkBehaviours
+ ///
class NetworkBehaviourProcessor
{
readonly List syncVars = new List();
readonly List syncObjects = new List();
- readonly Dictionary syncVarNetIds = new Dictionary(); //
- readonly List commands = new List();
- readonly List clientRpcs = new List();
+ //
+ readonly Dictionary syncVarNetIds = new Dictionary();
+ readonly List commands = new List();
+ readonly List clientRpcs = new List();
readonly List targetRpcs = new List();
readonly List eventRpcs = new List();
readonly List commandInvocationFuncs = new List();
@@ -21,12 +31,20 @@ class NetworkBehaviourProcessor
readonly List targetRpcInvocationFuncs = new List();
readonly List eventRpcInvocationFuncs = new List();
- readonly List commandCallFuncs = new List();
- readonly List clientRpcCallFuncs = new List();
- readonly List targetRpcCallFuncs = new List();
-
readonly TypeDefinition netBehaviourSubclass;
+ public struct CmdResult
+ {
+ public MethodDefinition method;
+ public bool ignoreAuthority;
+ }
+
+ public struct ClientRpcResult
+ {
+ public MethodDefinition method;
+ public bool excludeOwner;
+ }
+
public NetworkBehaviourProcessor(TypeDefinition td)
{
Weaver.DLog(td, "NetworkBehaviourProcessor");
@@ -37,7 +55,7 @@ public void Process()
{
if (netBehaviourSubclass.HasGenericParameters)
{
- Weaver.Error($"{netBehaviourSubclass} cannot have generic parameters");
+ Weaver.Error($"{netBehaviourSubclass.Name} cannot have generic parameters", netBehaviourSubclass);
return;
}
Weaver.DLog(netBehaviourSubclass, "Process Start");
@@ -101,7 +119,7 @@ public static void WriteServerActiveCheck(ILProcessor worker, string mdName, Ins
public static void WriteSetupLocals(ILProcessor worker)
{
worker.Body.InitLocals = true;
- worker.Body.Variables.Add(new VariableDefinition(Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkWriterType)));
+ worker.Body.Variables.Add(new VariableDefinition(Weaver.PooledNetworkWriterType));
}
public static void WriteCreateWriter(ILProcessor worker)
@@ -118,28 +136,50 @@ public static void WriteRecycleWriter(ILProcessor worker)
worker.Append(worker.Create(OpCodes.Call, Weaver.RecycleWriterReference));
}
- public static bool WriteArguments(ILProcessor worker, MethodDefinition md, bool skipFirst)
+ public static bool WriteArguments(ILProcessor worker, MethodDefinition method, RemoteCallType callType)
{
// write each argument
- short argNum = 1;
- foreach (ParameterDefinition pd in md.Parameters)
+ // example result
+ /*
+ writer.WritePackedInt32(someNumber);
+ writer.WriteNetworkIdentity(someTarget);
+ */
+
+ bool skipFirst = (callType == RemoteCallType.TargetRpc
+ && TargetRpcProcessor.HasNetworkConnectionParameter(method));
+
+ // arg of calling function, arg 0 is "this" so start counting at 1
+ int argNum = 1;
+ foreach (ParameterDefinition param in method.Parameters)
{
+ // NetworkConnection is not sent via the NetworkWriter so skip it here
+ // skip first for NetworkConnection in TargetRpc
if (argNum == 1 && skipFirst)
{
argNum += 1;
continue;
}
+ // skip SenderConnection in Command
+ if (IsSenderConnection(param, callType))
+ {
+ argNum += 1;
+ continue;
+ }
- MethodReference writeFunc = Writers.GetWriteFunc(pd.ParameterType);
+ MethodReference writeFunc = Writers.GetWriteFunc(param.ParameterType);
if (writeFunc == null)
{
- Weaver.Error($"{md} has invalid parameter {pd}" );
+ Weaver.Error($"{method.Name} has invalid parameter {param}", method);
return false;
}
+
// use built-in writer func on writer object
- worker.Append(worker.Create(OpCodes.Ldloc_0)); // writer object
- worker.Append(worker.Create(OpCodes.Ldarg, argNum)); // argument
- worker.Append(worker.Create(OpCodes.Call, writeFunc)); // call writer func on writer object
+ // NetworkWriter object
+ worker.Append(worker.Create(OpCodes.Ldloc_0));
+ // add argument to call
+ worker.Append(worker.Create(OpCodes.Ldarg, argNum));
+ // call writer extension method
+ worker.Append(worker.Create(OpCodes.Call, writeFunc));
argNum += 1;
}
return true;
@@ -151,7 +191,7 @@ public static bool WriteArguments(ILProcessor worker, MethodDefinition md, bool
// by adding an empty MirrorProcessed() function
public static bool WasProcessed(TypeDefinition td)
{
- return td.Methods.Any(method => method.Name == ProcessedFunctionName);
+ return td.GetMethod(ProcessedFunctionName) != null;
}
public static void MarkAsProcessed(TypeDefinition td)
@@ -174,29 +214,21 @@ void GenerateConstants()
Weaver.DLog(netBehaviourSubclass, " GenerateConstants ");
// find static constructor
- MethodDefinition cctor = null;
- bool cctorFound = false;
- foreach (MethodDefinition md in netBehaviourSubclass.Methods)
- {
- if (md.Name == ".cctor")
- {
- cctor = md;
- cctorFound = true;
- }
- }
+ MethodDefinition cctor = netBehaviourSubclass.GetMethod(".cctor");
+ bool cctorFound = cctor != null;
if (cctor != null)
{
// remove the return opcode from end of function. will add our own later.
if (cctor.Body.Instructions.Count != 0)
{
- Instruction ret = cctor.Body.Instructions[cctor.Body.Instructions.Count - 1];
- if (ret.OpCode == OpCodes.Ret)
+ Instruction retInstr = cctor.Body.Instructions[cctor.Body.Instructions.Count - 1];
+ if (retInstr.OpCode == OpCodes.Ret)
{
cctor.Body.Instructions.RemoveAt(cctor.Body.Instructions.Count - 1);
}
else
{
- Weaver.Error($"{netBehaviourSubclass} has invalid class constructor");
+ Weaver.Error($"{netBehaviourSubclass.Name} has invalid class constructor", cctor);
return;
}
}
@@ -213,56 +245,49 @@ void GenerateConstants()
}
// find instance constructor
- MethodDefinition ctor = null;
+ MethodDefinition ctor = netBehaviourSubclass.GetMethod(".ctor");
- foreach (MethodDefinition md in netBehaviourSubclass.Methods)
+ if (ctor == null)
{
- if (md.Name == ".ctor")
- {
- ctor = md;
-
- Instruction ret = ctor.Body.Instructions[ctor.Body.Instructions.Count - 1];
- if (ret.OpCode == OpCodes.Ret)
- {
- ctor.Body.Instructions.RemoveAt(ctor.Body.Instructions.Count - 1);
- }
- else
- {
- Weaver.Error($"{netBehaviourSubclass} has invalid constructor");
- return;
- }
-
- break;
- }
+ Weaver.Error($"{netBehaviourSubclass.Name} has invalid constructor", netBehaviourSubclass);
+ return;
}
- if (ctor == null)
+ Instruction ret = ctor.Body.Instructions[ctor.Body.Instructions.Count - 1];
+ if (ret.OpCode == OpCodes.Ret)
{
- Weaver.Error($"{netBehaviourSubclass} has invalid constructor");
+ ctor.Body.Instructions.RemoveAt(ctor.Body.Instructions.Count - 1);
+ }
+ else
+ {
+ Weaver.Error($"{netBehaviourSubclass.Name} has invalid constructor", ctor);
return;
}
+ // TODO: find out if the order below matters. If it doesn't split code below into 2 functions
ILProcessor ctorWorker = ctor.Body.GetILProcessor();
ILProcessor cctorWorker = cctor.Body.GetILProcessor();
for (int i = 0; i < commands.Count; ++i)
{
- GenerateRegisterCommandDelegate(cctorWorker, Weaver.registerCommandDelegateReference, commandInvocationFuncs[i], commands[i].Name);
+ CmdResult cmdResult = commands[i];
+ GenerateRegisterCommandDelegate(cctorWorker, Weaver.registerCommandDelegateReference, commandInvocationFuncs[i], cmdResult);
}
for (int i = 0; i < clientRpcs.Count; ++i)
{
- GenerateRegisterCommandDelegate(cctorWorker, Weaver.registerRpcDelegateReference, clientRpcInvocationFuncs[i], clientRpcs[i].Name);
+ ClientRpcResult clientRpcResult = clientRpcs[i];
+ GenerateRegisterRemoteDelegate(cctorWorker, Weaver.registerRpcDelegateReference, clientRpcInvocationFuncs[i], clientRpcResult.method.Name);
}
for (int i = 0; i < targetRpcs.Count; ++i)
{
- GenerateRegisterCommandDelegate(cctorWorker, Weaver.registerRpcDelegateReference, targetRpcInvocationFuncs[i], targetRpcs[i].Name);
+ GenerateRegisterRemoteDelegate(cctorWorker, Weaver.registerRpcDelegateReference, targetRpcInvocationFuncs[i], targetRpcs[i].Name);
}
for (int i = 0; i < eventRpcs.Count; ++i)
{
- GenerateRegisterCommandDelegate(cctorWorker, Weaver.registerEventDelegateReference, eventRpcInvocationFuncs[i], eventRpcs[i].Name);
+ GenerateRegisterRemoteDelegate(cctorWorker, Weaver.registerEventDelegateReference, eventRpcInvocationFuncs[i], eventRpcs[i].Name);
}
foreach (FieldDefinition fd in syncObjects)
@@ -287,27 +312,44 @@ void GenerateConstants()
// This generates code like:
NetworkBehaviour.RegisterCommandDelegate(base.GetType(), "CmdThrust", new NetworkBehaviour.CmdDelegate(ShipControl.InvokeCmdCmdThrust));
*/
- void GenerateRegisterCommandDelegate(ILProcessor awakeWorker, MethodReference registerMethod, MethodDefinition func, string cmdName)
+ void GenerateRegisterRemoteDelegate(ILProcessor worker, MethodReference registerMethod, MethodDefinition func, string cmdName)
{
- awakeWorker.Append(awakeWorker.Create(OpCodes.Ldtoken, netBehaviourSubclass));
- awakeWorker.Append(awakeWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference));
- awakeWorker.Append(awakeWorker.Create(OpCodes.Ldstr, cmdName));
- awakeWorker.Append(awakeWorker.Create(OpCodes.Ldnull));
- awakeWorker.Append(awakeWorker.Create(OpCodes.Ldftn, func));
-
- awakeWorker.Append(awakeWorker.Create(OpCodes.Newobj, Weaver.CmdDelegateConstructor));
- awakeWorker.Append(awakeWorker.Create(OpCodes.Call, registerMethod));
+ worker.Append(worker.Create(OpCodes.Ldtoken, netBehaviourSubclass));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference));
+ worker.Append(worker.Create(OpCodes.Ldstr, cmdName));
+ worker.Append(worker.Create(OpCodes.Ldnull));
+ worker.Append(worker.Create(OpCodes.Ldftn, func));
+
+ worker.Append(worker.Create(OpCodes.Newobj, Weaver.CmdDelegateConstructor));
+ //
+ worker.Append(worker.Create(OpCodes.Call, registerMethod));
+ }
+
+ void GenerateRegisterCommandDelegate(ILProcessor worker, MethodReference registerMethod, MethodDefinition func, CmdResult cmdResult)
+ {
+ string cmdName = cmdResult.method.Name;
+ bool ignoreAuthority = cmdResult.ignoreAuthority;
+
+ worker.Append(worker.Create(OpCodes.Ldtoken, netBehaviourSubclass));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference));
+ worker.Append(worker.Create(OpCodes.Ldstr, cmdName));
+ worker.Append(worker.Create(OpCodes.Ldnull));
+ worker.Append(worker.Create(OpCodes.Ldftn, func));
+
+ worker.Append(worker.Create(OpCodes.Newobj, Weaver.CmdDelegateConstructor));
+
+ worker.Append(worker.Create(ignoreAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0));
+
+ worker.Append(worker.Create(OpCodes.Call, registerMethod));
}
void GenerateSerialization()
{
Weaver.DLog(netBehaviourSubclass, " GenerateSerialization");
- foreach (MethodDefinition m in netBehaviourSubclass.Methods)
- {
- if (m.Name == "OnSerialize")
- return;
- }
+ const string SerializeMethodName = "SerializeSyncVars";
+ if (netBehaviourSubclass.GetMethod(SerializeMethodName) != null)
+ return;
if (syncVars.Count == 0)
{
@@ -315,13 +357,13 @@ void GenerateSerialization()
return;
}
- MethodDefinition serialize = new MethodDefinition("OnSerialize",
+ MethodDefinition serialize = new MethodDefinition(SerializeMethodName,
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
Weaver.boolType);
serialize.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkWriterType)));
serialize.Parameters.Add(new ParameterDefinition("forceAll", ParameterAttributes.None, Weaver.boolType));
- ILProcessor serWorker = serialize.Body.GetILProcessor();
+ ILProcessor worker = serialize.Body.GetILProcessor();
serialize.Body.InitLocals = true;
@@ -329,35 +371,42 @@ void GenerateSerialization()
VariableDefinition dirtyLocal = new VariableDefinition(Weaver.boolType);
serialize.Body.Variables.Add(dirtyLocal);
- MethodReference baseSerialize = Resolvers.ResolveMethodInParents(netBehaviourSubclass.BaseType, Weaver.CurrentAssembly, "OnSerialize");
+ MethodReference baseSerialize = Resolvers.TryResolveMethodInParents(netBehaviourSubclass.BaseType, Weaver.CurrentAssembly, SerializeMethodName);
if (baseSerialize != null)
{
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // writer
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // forceAll
- serWorker.Append(serWorker.Create(OpCodes.Call, baseSerialize));
- serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); // set dirtyLocal to result of base.OnSerialize()
+ // base
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ // writer
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ // forceAll
+ worker.Append(worker.Create(OpCodes.Ldarg_2));
+ worker.Append(worker.Create(OpCodes.Call, baseSerialize));
+ // set dirtyLocal to result of base.OnSerialize()
+ worker.Append(worker.Create(OpCodes.Stloc_0));
}
// Generates: if (forceAll);
- Instruction initialStateLabel = serWorker.Create(OpCodes.Nop);
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // forceAll
- serWorker.Append(serWorker.Create(OpCodes.Brfalse, initialStateLabel));
+ Instruction initialStateLabel = worker.Create(OpCodes.Nop);
+ // forceAll
+ worker.Append(worker.Create(OpCodes.Ldarg_2));
+ worker.Append(worker.Create(OpCodes.Brfalse, initialStateLabel));
foreach (FieldDefinition syncVar in syncVars)
{
// Generates a writer call for each sync variable
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // writer
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // this
- serWorker.Append(serWorker.Create(OpCodes.Ldfld, syncVar));
+ // writer
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ // this
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, syncVar));
MethodReference writeFunc = Writers.GetWriteFunc(syncVar.FieldType);
if (writeFunc != null)
{
- serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
+ worker.Append(worker.Create(OpCodes.Call, writeFunc));
}
else
{
- Weaver.Error($"{syncVar} has unsupported type. Use a supported Mirror type instead");
+ Weaver.Error($"{syncVar.Name} has unsupported type. Use a supported Mirror type instead", syncVar);
return;
}
}
@@ -365,18 +414,20 @@ void GenerateSerialization()
// always return true if forceAll
// Generates: return true
- serWorker.Append(serWorker.Create(OpCodes.Ldc_I4_1));
- serWorker.Append(serWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Ldc_I4_1));
+ worker.Append(worker.Create(OpCodes.Ret));
// Generates: end if (forceAll);
- serWorker.Append(initialStateLabel);
+ worker.Append(initialStateLabel);
// write dirty bits before the data fields
// Generates: writer.WritePackedUInt64 (base.get_syncVarDirtyBits ());
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // writer
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
- serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference));
- serWorker.Append(serWorker.Create(OpCodes.Call, Writers.GetWriteFunc(Weaver.uint64Type)));
+ // writer
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ // base
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference));
+ worker.Append(worker.Create(OpCodes.Call, Writers.GetWriteFunc(Weaver.uint64Type)));
// generate a writer call for any dirty variable in this class
@@ -384,150 +435,282 @@ void GenerateSerialization()
int dirtyBit = Weaver.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName);
foreach (FieldDefinition syncVar in syncVars)
{
- Instruction varLabel = serWorker.Create(OpCodes.Nop);
+ Instruction varLabel = worker.Create(OpCodes.Nop);
// Generates: if ((base.get_syncVarDirtyBits() & 1uL) != 0uL)
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
- serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference));
- serWorker.Append(serWorker.Create(OpCodes.Ldc_I8, 1L << dirtyBit)); // 8 bytes = long
- serWorker.Append(serWorker.Create(OpCodes.And));
- serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel));
+ // base
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference));
+ // 8 bytes = long
+ worker.Append(worker.Create(OpCodes.Ldc_I8, 1L << dirtyBit));
+ worker.Append(worker.Create(OpCodes.And));
+ worker.Append(worker.Create(OpCodes.Brfalse, varLabel));
// Generates a call to the writer for that field
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // writer
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
- serWorker.Append(serWorker.Create(OpCodes.Ldfld, syncVar));
+ // writer
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ // base
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, syncVar));
MethodReference writeFunc = Writers.GetWriteFunc(syncVar.FieldType);
if (writeFunc != null)
{
- serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
+ worker.Append(worker.Create(OpCodes.Call, writeFunc));
}
else
{
- Weaver.Error($"{syncVar} has unsupported type. Use a supported Mirror type instead");
+ Weaver.Error($"{syncVar.Name} has unsupported type. Use a supported Mirror type instead", syncVar);
return;
}
// something was dirty
- serWorker.Append(serWorker.Create(OpCodes.Ldc_I4_1));
- serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); // set dirtyLocal to true
+ worker.Append(worker.Create(OpCodes.Ldc_I4_1));
+ // set dirtyLocal to true
+ worker.Append(worker.Create(OpCodes.Stloc_0));
- serWorker.Append(varLabel);
+ worker.Append(varLabel);
dirtyBit += 1;
}
if (Weaver.GenerateLogErrors)
{
- serWorker.Append(serWorker.Create(OpCodes.Ldstr, "Injected Serialize " + netBehaviourSubclass.Name));
- serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.logErrorReference));
+ worker.Append(worker.Create(OpCodes.Ldstr, "Injected Serialize " + netBehaviourSubclass.Name));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.logErrorReference));
}
// generate: return dirtyLocal
- serWorker.Append(serWorker.Create(OpCodes.Ldloc_0));
- serWorker.Append(serWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Ldloc_0));
+ worker.Append(worker.Create(OpCodes.Ret));
netBehaviourSubclass.Methods.Add(serialize);
}
- public static int GetChannelId(CustomAttribute ca)
+ void DeserializeField(FieldDefinition syncVar, ILProcessor worker, MethodDefinition deserialize)
{
- foreach (CustomAttributeNamedArgument customField in ca.Fields)
+ // check for Hook function
+ MethodDefinition hookMethod = SyncVarProcessor.GetHookMethod(netBehaviourSubclass, syncVar);
+
+ if (IsNetworkIdentityField(syncVar))
{
- if (customField.Name == "channel")
- {
- return (int)customField.Argument.Value;
- }
+ DeserializeNetworkIdentityField(syncVar, worker, deserialize, hookMethod);
+ }
+ else
+ {
+ DeserializeNormalField(syncVar, worker, deserialize, hookMethod);
}
+ }
- return 0;
+ ///
+ /// Is the field a NetworkIdentity or GameObject
+ ///
+ ///
+ ///
+ static bool IsNetworkIdentityField(FieldDefinition syncVar)
+ {
+ return syncVar.FieldType.FullName == Weaver.gameObjectType.FullName ||
+ syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName;
}
- void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker, MethodDefinition deserialize)
+ ///
+ /// [SyncVar] GameObject/NetworkIdentity?
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ void DeserializeNetworkIdentityField(FieldDefinition syncVar, ILProcessor worker, MethodDefinition deserialize, MethodDefinition hookMethod)
{
- // check for Hook function
- if (!SyncVarProcessor.CheckForHookFunction(netBehaviourSubclass, syncVar, out MethodDefinition foundMethod))
+ /*
+ Generates code like:
+ uint oldNetId = ___qNetId;
+ // returns GetSyncVarGameObject(___qNetId)
+ GameObject oldSyncVar = syncvar.getter;
+ ___qNetId = reader.ReadPackedUInt32();
+ if (!SyncVarEqual(oldNetId, ref ___goNetId))
+ {
+ // getter returns GetSyncVarGameObject(___qNetId)
+ OnSetQ(oldSyncVar, syncvar.getter);
+ }
+ */
+
+ // GameObject/NetworkIdentity SyncVar:
+ // OnSerialize sends writer.Write(go);
+ // OnDeserialize reads to __netId manually so we can use
+ // lookups in the getter (so it still works if objects
+ // move in and out of range repeatedly)
+ FieldDefinition netIdField = syncVarNetIds[syncVar];
+
+ // uint oldNetId = ___qNetId;
+ VariableDefinition oldNetId = new VariableDefinition(Weaver.uint32Type);
+ deserialize.Body.Variables.Add(oldNetId);
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, netIdField));
+ worker.Append(worker.Create(OpCodes.Stloc, oldNetId));
+
+ // GameObject/NetworkIdentity oldSyncVar = syncvar.getter;
+ VariableDefinition oldSyncVar = new VariableDefinition(syncVar.FieldType);
+ deserialize.Body.Variables.Add(oldSyncVar);
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, syncVar));
+ worker.Append(worker.Create(OpCodes.Stloc, oldSyncVar));
+
+ // read id and store in netId field BEFORE calling the hook
+ // -> this makes way more sense. by definition, the hook is
+ // supposed to be called after it was changed. not before.
+ // -> setting it BEFORE calling the hook fixes the following bug:
+ // https://github.com/vis2k/Mirror/issues/1151 in host mode
+ // where the value during the Hook call would call Cmds on
+ // the host server, and they would all happen and compare
+ // values BEFORE the hook even returned and hence BEFORE the
+ // actual value was even set.
+ // put 'this.' onto stack for 'this.netId' below
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ // reader. for 'reader.Read()' below
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ // Read()
+ worker.Append(worker.Create(OpCodes.Call, Readers.GetReadFunc(Weaver.uint32Type)));
+ // netId
+ worker.Append(worker.Create(OpCodes.Stfld, netIdField));
+
+ if (hookMethod != null)
{
- return;
+ // call Hook(this.GetSyncVarGameObject/NetworkIdentity(reader.ReadPackedUInt32()))
+ // because we send/receive the netID, not the GameObject/NetworkIdentity
+ // but only if SyncVar changed. otherwise a client would
+ // get hook calls for all initial values, even if they
+ // didn't change from the default values on the client.
+ // see also: https://github.com/vis2k/Mirror/issues/1278
+
+ // IMPORTANT: for GameObjects/NetworkIdentities we usually
+ // use SyncVarGameObjectEqual to compare equality.
+ // in this case however, we can just use
+ // SyncVarEqual with the two uint netIds.
+ // => this is easier weaver code because we don't
+ // have to get the GameObject/NetworkIdentity
+ // from the uint netId
+ // => this is faster because we void one
+ // GetComponent call for GameObjects to get
+ // their NetworkIdentity when comparing.
+
+ // Generates: if (!SyncVarEqual);
+ Instruction syncVarEqualLabel = worker.Create(OpCodes.Nop);
+
+ // 'this.' for 'this.SyncVarEqual'
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ // 'oldNetId'
+ worker.Append(worker.Create(OpCodes.Ldloc, oldNetId));
+ // 'ref this.__netId'
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldflda, netIdField));
+ // call the function
+ GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(Weaver.syncVarEqualReference);
+ syncVarEqualGm.GenericArguments.Add(netIdField.FieldType);
+ worker.Append(worker.Create(OpCodes.Call, syncVarEqualGm));
+ worker.Append(worker.Create(OpCodes.Brtrue, syncVarEqualLabel));
+
+ // call the hook
+ // Generates: OnValueChanged(oldValue, this.syncVar);
+ SyncVarProcessor.WriteCallHookMethodUsingField(worker, hookMethod, oldSyncVar, syncVar);
+
+ // Generates: end if (!SyncVarEqual);
+ worker.Append(syncVarEqualLabel);
}
+ }
- if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName ||
- syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
- {
- // GameObject/NetworkIdentity SyncVar:
- // OnSerialize sends writer.Write(go);
- // OnDeserialize reads to __netId manually so we can use
- // lookups in the getter (so it still works if objects
- // move in and out of range repeatedly)
- FieldDefinition netIdField = syncVarNetIds[syncVar];
-
- VariableDefinition tmpValue = new VariableDefinition(Weaver.uint32Type);
- deserialize.Body.Variables.Add(tmpValue);
-
- // read id and store in a local variable
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
- serWorker.Append(serWorker.Create(OpCodes.Call, Readers.GetReadFunc(Weaver.uint32Type)));
- serWorker.Append(serWorker.Create(OpCodes.Stloc, tmpValue));
-
- if (foundMethod != null)
+ ///
+ /// [SyncVar] int/float/struct/etc.?
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ void DeserializeNormalField(FieldDefinition syncVar, ILProcessor serWorker, MethodDefinition deserialize, MethodDefinition hookMethod)
+ {
+ /*
+ Generates code like:
+ // for hook
+ int oldValue = a;
+ Networka = reader.ReadPackedInt32();
+ if (!SyncVarEqual(oldValue, ref a))
{
- // call Hook(this.GetSyncVarGameObject/NetworkIdentity(reader.ReadPackedUInt32()))
- // because we send/receive the netID, not the GameObject/NetworkIdentity
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // this.
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
- serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
- serWorker.Append(serWorker.Create(OpCodes.Ldflda, syncVar));
- if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName)
- serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarGameObjectReference));
- else if (syncVar.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
- serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.getSyncVarNetworkIdentityReference));
- serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));
+ OnSetA(oldValue, Networka);
}
- // set the netid field
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
- serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
- serWorker.Append(serWorker.Create(OpCodes.Stfld, netIdField));
+ */
+
+ MethodReference readFunc = Readers.GetReadFunc(syncVar.FieldType);
+ if (readFunc == null)
+ {
+ Weaver.Error($"{syncVar.Name} has unsupported type. Use a supported Mirror type instead", syncVar);
+ return;
}
- else
+
+ // T oldValue = value;
+ VariableDefinition oldValue = new VariableDefinition(syncVar.FieldType);
+ deserialize.Body.Variables.Add(oldValue);
+ serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
+ serWorker.Append(serWorker.Create(OpCodes.Ldfld, syncVar));
+ serWorker.Append(serWorker.Create(OpCodes.Stloc, oldValue));
+
+ // read value and store in syncvar BEFORE calling the hook
+ // -> this makes way more sense. by definition, the hook is
+ // supposed to be called after it was changed. not before.
+ // -> setting it BEFORE calling the hook fixes the following bug:
+ // https://github.com/vis2k/Mirror/issues/1151 in host mode
+ // where the value during the Hook call would call Cmds on
+ // the host server, and they would all happen and compare
+ // values BEFORE the hook even returned and hence BEFORE the
+ // actual value was even set.
+ // put 'this.' onto stack for 'this.syncvar' below
+ serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
+ // reader. for 'reader.Read()' below
+ serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
+ // reader.Read()
+ serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
+ // syncvar
+ serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar));
+
+ if (hookMethod != null)
{
- MethodReference readFunc = Readers.GetReadFunc(syncVar.FieldType);
- if (readFunc == null)
- {
- Weaver.Error($"{syncVar} has unsupported type. Use a supported Mirror type instead");
- return;
- }
- VariableDefinition tmpValue = new VariableDefinition(syncVar.FieldType);
- deserialize.Body.Variables.Add(tmpValue);
+ // call hook
+ // but only if SyncVar changed. otherwise a client would
+ // get hook calls for all initial values, even if they
+ // didn't change from the default values on the client.
+ // see also: https://github.com/vis2k/Mirror/issues/1278
- // read value and put it in a local variable
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
- serWorker.Append(serWorker.Create(OpCodes.Call, readFunc));
- serWorker.Append(serWorker.Create(OpCodes.Stloc, tmpValue));
+ // Generates: if (!SyncVarEqual);
+ Instruction syncVarEqualLabel = serWorker.Create(OpCodes.Nop);
- if (foundMethod != null)
- {
- // call hook
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
- serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
- serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod));
- }
- // set the property
+ // 'this.' for 'this.SyncVarEqual'
+ serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
+ // 'oldValue'
+ serWorker.Append(serWorker.Create(OpCodes.Ldloc, oldValue));
+ // 'ref this.syncVar'
serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
- serWorker.Append(serWorker.Create(OpCodes.Ldloc, tmpValue));
- serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar));
+ serWorker.Append(serWorker.Create(OpCodes.Ldflda, syncVar));
+ // call the function
+ GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(Weaver.syncVarEqualReference);
+ syncVarEqualGm.GenericArguments.Add(syncVar.FieldType);
+ serWorker.Append(serWorker.Create(OpCodes.Call, syncVarEqualGm));
+ serWorker.Append(serWorker.Create(OpCodes.Brtrue, syncVarEqualLabel));
+
+ // call the hook
+ // Generates: OnValueChanged(oldValue, this.syncVar);
+ SyncVarProcessor.WriteCallHookMethodUsingField(serWorker, hookMethod, oldValue, syncVar);
+
+ // Generates: end if (!SyncVarEqual);
+ serWorker.Append(syncVarEqualLabel);
}
-
}
void GenerateDeSerialization()
{
Weaver.DLog(netBehaviourSubclass, " GenerateDeSerialization");
- foreach (MethodDefinition m in netBehaviourSubclass.Methods)
- {
- if (m.Name == "OnDeserialize")
- return;
- }
+ const string DeserializeMethodName = "DeserializeSyncVars";
+ if (netBehaviourSubclass.GetMethod(DeserializeMethodName) != null)
+ return;
if (syncVars.Count == 0)
{
@@ -535,7 +718,7 @@ void GenerateDeSerialization()
return;
}
- MethodDefinition serialize = new MethodDefinition("OnDeserialize",
+ MethodDefinition serialize = new MethodDefinition(DeserializeMethodName,
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
Weaver.voidType);
@@ -547,12 +730,15 @@ void GenerateDeSerialization()
VariableDefinition dirtyBitsLocal = new VariableDefinition(Weaver.int64Type);
serialize.Body.Variables.Add(dirtyBitsLocal);
- MethodReference baseDeserialize = Resolvers.ResolveMethodInParents(netBehaviourSubclass.BaseType, Weaver.CurrentAssembly, "OnDeserialize");
+ MethodReference baseDeserialize = Resolvers.TryResolveMethodInParents(netBehaviourSubclass.BaseType, Weaver.CurrentAssembly, DeserializeMethodName);
if (baseDeserialize != null)
{
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // reader
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // initialState
+ // base
+ serWorker.Append(serWorker.Create(OpCodes.Ldarg_0));
+ // reader
+ serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
+ // initialState
+ serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
serWorker.Append(serWorker.Create(OpCodes.Call, baseDeserialize));
}
@@ -572,14 +758,14 @@ void GenerateDeSerialization()
// Generates: end if (initialState);
serWorker.Append(initialStateLabel);
-
// get dirty bits
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Call, Readers.GetReadFunc(Weaver.uint64Type)));
serWorker.Append(serWorker.Create(OpCodes.Stloc_0));
// conditionally read each syncvar
- int dirtyBit = Weaver.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName); // start at number of syncvars in parent
+ // start at number of syncvars in parent
+ int dirtyBit = Weaver.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName);
foreach (FieldDefinition syncVar in syncVars)
{
Instruction varLabel = serWorker.Create(OpCodes.Nop);
@@ -606,38 +792,55 @@ void GenerateDeSerialization()
netBehaviourSubclass.Methods.Add(serialize);
}
- public static bool ProcessNetworkReaderParameters(MethodDefinition md, ILProcessor worker, bool skipFirst)
+ public static bool ReadArguments(MethodDefinition method, ILProcessor worker, RemoteCallType callType)
{
- int count = 0;
-
- // read cmd args from NetworkReader
- foreach (ParameterDefinition arg in md.Parameters)
+ // read each argument
+ // example result
+ /*
+ CallCmdDoSomething(reader.ReadPackedInt32(), reader.ReadNetworkIdentity());
+ */
+
+ bool skipFirst = (callType == RemoteCallType.TargetRpc
+ && TargetRpcProcessor.HasNetworkConnectionParameter(method));
+
+ // arg of calling function, arg 0 is "this" so start counting at 1
+ int argNum = 1;
+ foreach (ParameterDefinition param in method.Parameters)
{
- if (count++ == 0 && skipFirst)
+ // NetworkConnection is not sent via the NetworkWriter so skip it here
+ // skip first for NetworkConnection in TargetRpc
+ if (argNum == 1 && skipFirst)
{
+ argNum += 1;
continue;
}
- MethodReference readFunc = Readers.GetReadFunc(arg.ParameterType); //?
+ // skip SenderConnection in Command
+ if (IsSenderConnection(param, callType))
+ {
+ argNum += 1;
+ continue;
+ }
+
+
+ MethodReference readFunc = Readers.GetReadFunc(param.ParameterType);
- if (readFunc != null)
+ if (readFunc == null)
{
- worker.Append(worker.Create(OpCodes.Ldarg_1));
- worker.Append(worker.Create(OpCodes.Call, readFunc));
+ Weaver.Error($"{method.Name} has invalid parameter {param}. Unsupported type {param.ParameterType}, use a supported Mirror type instead", method);
+ return false;
+ }
- // conversion.. is this needed?
- if (arg.ParameterType.FullName == Weaver.singleType.FullName)
- {
- worker.Append(worker.Create(OpCodes.Conv_R4));
- }
- else if (arg.ParameterType.FullName == Weaver.doubleType.FullName)
- {
- worker.Append(worker.Create(OpCodes.Conv_R8));
- }
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ worker.Append(worker.Create(OpCodes.Call, readFunc));
+
+ // conversion.. is this needed?
+ if (param.ParameterType.FullName == Weaver.singleType.FullName)
+ {
+ worker.Append(worker.Create(OpCodes.Conv_R4));
}
- else
+ else if (param.ParameterType.FullName == Weaver.doubleType.FullName)
{
- Weaver.Error($"{md} has invalid parameter {arg}. Unsupported type {arg.ParameterType}, use a supported Mirror type instead");
- return false;
+ worker.Append(worker.Create(OpCodes.Conv_R8));
}
}
return true;
@@ -645,80 +848,107 @@ public static bool ProcessNetworkReaderParameters(MethodDefinition md, ILProcess
public static void AddInvokeParameters(ICollection collection)
{
- collection.Add(new ParameterDefinition("obj", ParameterAttributes.None, Weaver.NetworkBehaviourType2));
+ collection.Add(new ParameterDefinition("obj", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkBehaviourType)));
collection.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
+ // senderConnection is only used for commands but NetworkBehaviour.CmdDelegate is used for all remote calls
+ collection.Add(new ParameterDefinition("senderConnection", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkConnectionType)));
}
public static bool ProcessMethodsValidateFunction(MethodReference md)
{
if (md.ReturnType.FullName == Weaver.IEnumeratorType.FullName)
{
- Weaver.Error($"{md} cannot be a coroutine");
+ Weaver.Error($"{md.Name} cannot be a coroutine", md);
return false;
}
if (md.ReturnType.FullName != Weaver.voidType.FullName)
{
- Weaver.Error($"{md} cannot return a value. Make it void instead");
+ Weaver.Error($"{md.Name} cannot return a value. Make it void instead", md);
return false;
}
if (md.HasGenericParameters)
{
- Weaver.Error($"{md} cannot have generic parameters");
+ Weaver.Error($"{md.Name} cannot have generic parameters", md);
return false;
}
return true;
}
- public static bool ProcessMethodsValidateParameters(MethodReference md, CustomAttribute ca)
+ public static bool ProcessMethodsValidateParameters(MethodReference method, RemoteCallType callType)
{
- for (int i = 0; i < md.Parameters.Count; ++i)
+ for (int i = 0; i < method.Parameters.Count; ++i)
{
- ParameterDefinition p = md.Parameters[i];
- if (p.IsOut)
- {
- Weaver.Error($"{md} cannot have out parameters");
- return false;
- }
- if (p.IsOptional)
- {
- Weaver.Error($"{md} cannot have optional parameters");
- return false;
- }
- if (p.ParameterType.Resolve().IsAbstract)
- {
- Weaver.Error($"{md} has invalid parameter {p}. Use concrete type instead of abstract type {p.ParameterType}");
- return false;
- }
- if (p.ParameterType.IsByReference)
+ ParameterDefinition param = method.Parameters[i];
+
+ bool valid = ValidateParameter(method, param, callType, i == 0);
+
+ if (!valid)
{
- Weaver.Error($"{md} has invalid parameter {p}. Use supported type instead of reference type {p.ParameterType}");
return false;
}
- // TargetRPC is an exception to this rule and can have a NetworkConnection as first parameter
- if (p.ParameterType.FullName == Weaver.NetworkConnectionType.FullName &&
- !(ca.AttributeType.FullName == Weaver.TargetRpcType.FullName && i == 0))
+ }
+ return true;
+ }
+
+ static bool ValidateParameter(MethodReference method, ParameterDefinition param, RemoteCallType callType, bool firstParam)
+ {
+ bool isNetworkConnection = param.ParameterType.FullName == Weaver.NetworkConnectionType.FullName;
+ bool isSenderConnection = IsSenderConnection(param, callType);
+
+ if (param.IsOut)
+ {
+ Weaver.Error($"{method.Name} cannot have out parameters", method);
+ return false;
+ }
+
+
+ // if not SenderConnection And not TargetRpc NetworkConnection first param
+ if (!isSenderConnection && isNetworkConnection && !(callType == RemoteCallType.TargetRpc && firstParam))
+ {
+ if (callType == RemoteCallType.Command)
{
- Weaver.Error($"{md} has invalid parameer {p}. Cannot pass NeworkConnections");
- return false;
+ Weaver.Error($"{method.Name} has invalid parameter {param}, Cannot pass NetworkConnections. Instead use 'NetworkConnectionToClient conn = null' to get the sender's connection on the server", method);
}
- if (p.ParameterType.Resolve().IsDerivedFrom(Weaver.ComponentType))
+ else
{
- if (p.ParameterType.FullName != Weaver.NetworkIdentityType.FullName)
- {
- Weaver.Error($"{md} has invalid parameter {p}. Cannot pass components in remote method calls");
- return false;
- }
+ Weaver.Error($"{method.Name} has invalid parameter {param}. Cannot pass NetworkConnections", method);
}
+ return false;
}
+
+ // sender connection can be optional
+ if (param.IsOptional && !isSenderConnection)
+ {
+ Weaver.Error($"{method.Name} cannot have optional parameters", method);
+ return false;
+ }
+
return true;
}
+ public static bool IsSenderConnection(ParameterDefinition param, RemoteCallType callType)
+ {
+ if (callType != RemoteCallType.Command)
+ {
+ return false;
+ }
+
+ TypeReference type = param.ParameterType;
+
+ const string ConnectionToClient = "Mirror.NetworkConnectionToClient";
+ bool isConnectionToClient = type.FullName == ConnectionToClient || type.Resolve().IsDerivedFrom(ConnectionToClient);
+
+ return isConnectionToClient;
+ }
+
void ProcessMethods()
{
HashSet names = new HashSet();
+ // copy the list of methods because we will be adding methods in the loop
+ List methods = new List(netBehaviourSubclass.Methods);
// find command and RPC functions
- foreach (MethodDefinition md in netBehaviourSubclass.Methods)
+ foreach (MethodDefinition md in methods)
{
foreach (CustomAttribute ca in md.CustomAttributes)
{
@@ -741,118 +971,106 @@ void ProcessMethods()
}
}
}
+ }
- // cmds
- foreach (MethodDefinition md in commandInvocationFuncs)
- {
- netBehaviourSubclass.Methods.Add(md);
- }
- foreach (MethodDefinition md in commandCallFuncs)
- {
- netBehaviourSubclass.Methods.Add(md);
- }
-
- // rpcs
- foreach (MethodDefinition md in clientRpcInvocationFuncs)
- {
- netBehaviourSubclass.Methods.Add(md);
- }
- foreach (MethodDefinition md in targetRpcInvocationFuncs)
- {
- netBehaviourSubclass.Methods.Add(md);
- }
- foreach (MethodDefinition md in clientRpcCallFuncs)
- {
- netBehaviourSubclass.Methods.Add(md);
- }
- foreach (MethodDefinition md in targetRpcCallFuncs)
+ void ProcessClientRpc(HashSet names, MethodDefinition md, CustomAttribute clientRpcAttr)
+ {
+ if (md.IsAbstract)
{
- netBehaviourSubclass.Methods.Add(md);
+ Weaver.Error("Abstract ClientRpc are currently not supported, use virtual method instead", md);
+ return;
}
- }
- void ProcessClientRpc(HashSet names, MethodDefinition md, CustomAttribute ca)
- {
- if (!RpcProcessor.ProcessMethodsValidateRpc(md, ca))
+ if (!RpcProcessor.ProcessMethodsValidateRpc(md))
{
return;
}
if (names.Contains(md.Name))
{
- Weaver.Error("Duplicate ClientRpc name [" + netBehaviourSubclass.FullName + ":" + md.Name + "]");
+ Weaver.Error($"Duplicate ClientRpc name {md.Name}", md);
return;
}
+
+ bool excludeOwner = clientRpcAttr.GetField("excludeOwner", false);
+
names.Add(md.Name);
- clientRpcs.Add(md);
+ clientRpcs.Add(new ClientRpcResult
+ {
+ method = md,
+ excludeOwner = excludeOwner
+ });
- MethodDefinition rpcCallFunc = RpcProcessor.ProcessRpcCall(netBehaviourSubclass, md, ca);
+ MethodDefinition rpcCallFunc = RpcProcessor.ProcessRpcCall(netBehaviourSubclass, md, clientRpcAttr);
MethodDefinition rpcFunc = RpcProcessor.ProcessRpcInvoke(netBehaviourSubclass, md, rpcCallFunc);
if (rpcFunc != null)
{
clientRpcInvocationFuncs.Add(rpcFunc);
}
+ }
- if (rpcCallFunc != null)
+ void ProcessTargetRpc(HashSet names, MethodDefinition md, CustomAttribute targetRpcAttr)
+ {
+ if (md.IsAbstract)
{
- clientRpcCallFuncs.Add(rpcCallFunc);
+ Weaver.Error("Abstract TargetRpc are currently not supported, use virtual method instead", md);
+ return;
}
- }
- void ProcessTargetRpc(HashSet names, MethodDefinition md, CustomAttribute ca)
- {
- if (!TargetRpcProcessor.ProcessMethodsValidateTargetRpc(md, ca))
+ if (!TargetRpcProcessor.ProcessMethodsValidateTargetRpc(md))
return;
if (names.Contains(md.Name))
{
- Weaver.Error("Duplicate Target Rpc name [" + netBehaviourSubclass.FullName + ":" + md.Name + "]");
+ Weaver.Error($"Duplicate Target Rpc name {md.Name}", md);
return;
}
names.Add(md.Name);
targetRpcs.Add(md);
- MethodDefinition rpcCallFunc = TargetRpcProcessor.ProcessTargetRpcCall(netBehaviourSubclass, md, ca);
+ MethodDefinition rpcCallFunc = TargetRpcProcessor.ProcessTargetRpcCall(netBehaviourSubclass, md, targetRpcAttr);
MethodDefinition rpcFunc = TargetRpcProcessor.ProcessTargetRpcInvoke(netBehaviourSubclass, md, rpcCallFunc);
if (rpcFunc != null)
{
targetRpcInvocationFuncs.Add(rpcFunc);
}
+ }
- if (rpcCallFunc != null)
+ void ProcessCommand(HashSet names, MethodDefinition md, CustomAttribute commandAttr)
+ {
+ if (md.IsAbstract)
{
- targetRpcCallFuncs.Add(rpcCallFunc);
+ Weaver.Error("Abstract Commands are currently not supported, use virtual method instead", md);
+ return;
}
- }
- void ProcessCommand(HashSet names, MethodDefinition md, CustomAttribute ca)
- {
- if (!CommandProcessor.ProcessMethodsValidateCommand(md, ca))
+ if (!CommandProcessor.ProcessMethodsValidateCommand(md))
return;
if (names.Contains(md.Name))
{
- Weaver.Error("Duplicate Command name [" + netBehaviourSubclass.FullName + ":" + md.Name + "]");
+ Weaver.Error($"Duplicate Command name {md.Name}", md);
return;
}
+ bool ignoreAuthority = commandAttr.GetField("ignoreAuthority", false);
+
names.Add(md.Name);
- commands.Add(md);
+ commands.Add(new CmdResult
+ {
+ method = md,
+ ignoreAuthority = ignoreAuthority
+ });
- MethodDefinition cmdCallFunc = CommandProcessor.ProcessCommandCall(netBehaviourSubclass, md, ca);
+ MethodDefinition cmdCallFunc = CommandProcessor.ProcessCommandCall(netBehaviourSubclass, md, commandAttr);
MethodDefinition cmdFunc = CommandProcessor.ProcessCommandInvoke(netBehaviourSubclass, md, cmdCallFunc);
if (cmdFunc != null)
{
commandInvocationFuncs.Add(cmdFunc);
}
-
- if (cmdCallFunc != null)
- {
- commandCallFuncs.Add(cmdCallFunc);
- }
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/PropertySiteProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/PropertySiteProcessor.cs
index eb78b6d..597094e 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/PropertySiteProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/PropertySiteProcessor.cs
@@ -57,32 +57,15 @@ static void ProcessSiteMethod(TypeDefinition td, MethodDefinition md)
if (md.Name == ".cctor" ||
md.Name == NetworkBehaviourProcessor.ProcessedFunctionName ||
- md.Name.StartsWith("InvokeSyn"))
+ md.Name.StartsWith(Weaver.InvokeRpcPrefix))
return;
if (md.Body != null && md.Body.Instructions != null)
{
// TODO move this to NetworkBehaviourProcessor
- foreach (CustomAttribute attr in md.CustomAttributes)
- {
- switch (attr.Constructor.DeclaringType.ToString())
- {
- case "Mirror.ServerAttribute":
- InjectServerGuard(td, md, true);
- break;
- case "Mirror.ServerCallbackAttribute":
- InjectServerGuard(td, md, false);
- break;
- case "Mirror.ClientAttribute":
- InjectClientGuard(td, md, true);
- break;
- case "Mirror.ClientCallbackAttribute":
- InjectClientGuard(td, md, false);
- break;
- }
- }
+ ServerClientAttributeProcessor.ProcessMethodAttributes(td, md);
- for (int iCount= 0; iCount < md.Body.Instructions.Count;)
+ for (int iCount = 0; iCount < md.Body.Instructions.Count;)
{
Instruction instr = md.Body.Instructions[iCount];
iCount += ProcessInstruction(md, instr, iCount);
@@ -90,51 +73,6 @@ static void ProcessSiteMethod(TypeDefinition td, MethodDefinition md)
}
}
- static void InjectServerGuard(TypeDefinition td, MethodDefinition md, bool logWarning)
- {
- if (!Weaver.IsNetworkBehaviour(td))
- {
- Weaver.Error($"[Server] {md} must be declared in a NetworkBehaviour");
- return;
- }
- ILProcessor worker = md.Body.GetILProcessor();
- Instruction top = md.Body.Instructions[0];
-
- worker.InsertBefore(top, worker.Create(OpCodes.Call, Weaver.NetworkServerGetActive));
- worker.InsertBefore(top, worker.Create(OpCodes.Brtrue, top));
- if (logWarning)
- {
- worker.InsertBefore(top, worker.Create(OpCodes.Ldstr, "[Server] function '" + md.FullName + "' called on client"));
- worker.InsertBefore(top, worker.Create(OpCodes.Call, Weaver.logWarningReference));
- }
- InjectGuardParameters(md, worker, top);
- InjectGuardReturnValue(md, worker, top);
- worker.InsertBefore(top, worker.Create(OpCodes.Ret));
- }
-
- static void InjectClientGuard(TypeDefinition td, MethodDefinition md, bool logWarning)
- {
- if (!Weaver.IsNetworkBehaviour(td))
- {
- Weaver.Error($"[Client] {md} must be declared in a NetworkBehaviour");
- return;
- }
- ILProcessor worker = md.Body.GetILProcessor();
- Instruction top = md.Body.Instructions[0];
-
- worker.InsertBefore(top, worker.Create(OpCodes.Call, Weaver.NetworkClientGetActive));
- worker.InsertBefore(top, worker.Create(OpCodes.Brtrue, top));
- if (logWarning)
- {
- worker.InsertBefore(top, worker.Create(OpCodes.Ldstr, "[Client] function '" + md.FullName + "' called on server"));
- worker.InsertBefore(top, worker.Create(OpCodes.Call, Weaver.logWarningReference));
- }
-
- InjectGuardParameters(md, worker, top);
- InjectGuardReturnValue(md, worker, top);
- worker.InsertBefore(top, worker.Create(OpCodes.Ret));
- }
-
// replaces syncvar write access with the NetworkXYZ.get property calls
static void ProcessInstructionSetterField(MethodDefinition md, Instruction i, FieldDefinition opField)
{
@@ -173,41 +111,29 @@ static void ProcessInstructionGetterField(MethodDefinition md, Instruction i, Fi
static int ProcessInstruction(MethodDefinition md, Instruction instr, int iCount)
{
- if (instr.OpCode == OpCodes.Call || instr.OpCode == OpCodes.Callvirt)
+ if ((instr.OpCode == OpCodes.Call || instr.OpCode == OpCodes.Callvirt)
+ && instr.Operand is MethodReference opMethod)
{
- if (instr.Operand is MethodReference opMethod)
- {
- ProcessInstructionMethod(md, instr, opMethod, iCount);
- }
+ ProcessInstructionMethod(md, instr, opMethod, iCount);
}
- if (instr.OpCode == OpCodes.Stfld)
+ if (instr.OpCode == OpCodes.Stfld && instr.Operand is FieldDefinition opFieldst)
{
// this instruction sets the value of a field. cache the field reference.
- if (instr.Operand is FieldDefinition opField)
- {
- ProcessInstructionSetterField(md, instr, opField);
- }
+ ProcessInstructionSetterField(md, instr, opFieldst);
}
- if (instr.OpCode == OpCodes.Ldfld)
+ if (instr.OpCode == OpCodes.Ldfld && instr.Operand is FieldDefinition opFieldld)
{
// this instruction gets the value of a field. cache the field reference.
- if (instr.Operand is FieldDefinition opField)
- {
- ProcessInstructionGetterField(md, instr, opField);
- }
+ ProcessInstructionGetterField(md, instr, opFieldld);
}
- if (instr.OpCode == OpCodes.Ldflda)
+ if (instr.OpCode == OpCodes.Ldflda && instr.Operand is FieldDefinition opFieldlda)
{
// loading a field by reference, watch out for initobj instruction
// see https://github.com/vis2k/Mirror/issues/696
-
- if (instr.Operand is FieldDefinition opField)
- {
- return ProcessInstructionLoadAddress(md, instr, opField, iCount);
- }
+ return ProcessInstructionLoadAddress(md, instr, opFieldlda, iCount);
}
return 1;
@@ -253,89 +179,34 @@ static int ProcessInstructionLoadAddress(MethodDefinition md, Instruction instr,
static void ProcessInstructionMethod(MethodDefinition md, Instruction instr, MethodReference opMethodRef, int iCount)
{
- //DLog(td, "ProcessInstructionMethod " + opMethod.Name);
- if (opMethodRef.Name == "Invoke")
- {
- // Events use an "Invoke" method to call the delegate.
- // this code replaces the "Invoke" instruction with the generated "Call***" instruction which send the event to the server.
- // but the "Invoke" instruction is called on the event field - where the "call" instruction is not.
- // so the earlier instruction that loads the event field is replaced with a Noop.
-
- // go backwards until find a ldfld instruction that matches ANY event
- bool found = false;
- while (iCount > 0 && !found)
- {
- iCount -= 1;
- Instruction inst = md.Body.Instructions[iCount];
- if (inst.OpCode == OpCodes.Ldfld)
- {
- FieldReference opField = inst.Operand as FieldReference;
-
- // find replaceEvent with matching name
- // NOTE: original weaver compared .Name, not just the MethodDefinition,
- // that's why we use dict.
- if (Weaver.WeaveLists.replaceEvents.TryGetValue(opField.Name, out MethodDefinition replacement))
- {
- instr.Operand = replacement;
- inst.OpCode = OpCodes.Nop;
- found = true;
- }
- }
- }
- }
- }
+ if (opMethodRef.Name != "Invoke")
+ return;
+ // Events use an "Invoke" method to call the delegate.
+ // this code replaces the "Invoke" instruction with the generated "Call***" instruction which send the event to the server.
+ // but the "Invoke" instruction is called on the event field - where the "call" instruction is not.
+ // so the earlier instruction that loads the event field is replaced with a Noop.
- // this is required to early-out from a function with "ref" or "out" parameters
- static void InjectGuardParameters(MethodDefinition md, ILProcessor worker, Instruction top)
- {
- int offset = md.Resolve().IsStatic ? 0 : 1;
- for (int index = 0; index < md.Parameters.Count; index++)
+ // go backwards until find a ldfld instruction that matches ANY event
+ while (iCount > 0)
{
- ParameterDefinition param = md.Parameters[index];
- if (param.IsOut)
+ iCount -= 1;
+ Instruction inst = md.Body.Instructions[iCount];
+ if (inst.OpCode == OpCodes.Ldfld)
{
- TypeReference elementType = param.ParameterType.GetElementType();
- if (elementType.IsPrimitive)
- {
- worker.InsertBefore(top, worker.Create(OpCodes.Ldarg, index + offset));
- worker.InsertBefore(top, worker.Create(OpCodes.Ldc_I4_0));
- worker.InsertBefore(top, worker.Create(OpCodes.Stind_I4));
- }
- else
- {
- md.Body.Variables.Add(new VariableDefinition(elementType));
- md.Body.InitLocals = true;
+ FieldReference opField = inst.Operand as FieldReference;
- worker.InsertBefore(top, worker.Create(OpCodes.Ldarg, index + offset));
- worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, (byte)(md.Body.Variables.Count - 1)));
- worker.InsertBefore(top, worker.Create(OpCodes.Initobj, elementType));
- worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, md.Body.Variables.Count - 1));
- worker.InsertBefore(top, worker.Create(OpCodes.Stobj, elementType));
+ // find replaceEvent with matching name
+ // NOTE: original weaver compared .Name, not just the MethodDefinition,
+ // that's why we use dict.
+ if (Weaver.WeaveLists.replaceEvents.TryGetValue(opField.FullName, out MethodDefinition replacement))
+ {
+ instr.Operand = replacement;
+ inst.OpCode = OpCodes.Nop;
+ return;
}
}
}
}
-
- // this is required to early-out from a function with a return value.
- static void InjectGuardReturnValue(MethodDefinition md, ILProcessor worker, Instruction top)
- {
- if (md.ReturnType.FullName != Weaver.voidType.FullName)
- {
- if (md.ReturnType.IsPrimitive)
- {
- worker.InsertBefore(top, worker.Create(OpCodes.Ldc_I4_0));
- }
- else
- {
- md.Body.Variables.Add(new VariableDefinition(md.ReturnType));
- md.Body.InitLocals = true;
-
- worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, (byte)(md.Body.Variables.Count - 1)));
- worker.InsertBefore(top, worker.Create(OpCodes.Initobj, md.ReturnType));
- worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, md.Body.Variables.Count - 1));
- }
- }
- }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs
index d87bf22..e69afcd 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs
@@ -1,9 +1,6 @@
-using System;
+using System.IO;
using Mono.CecilX;
using UnityEditor.Compilation;
-using System.Linq;
-using System.Collections.Generic;
-using System.IO;
namespace Mirror.Weaver
{
@@ -27,7 +24,7 @@ public static void ProcessReadersAndWriters(AssemblyDefinition CurrentAssembly)
ProcessAssemblyClasses(CurrentAssembly, assembly);
}
}
- catch(FileNotFoundException)
+ catch (FileNotFoundException)
{
// During first import, this gets called before some assemblies
// are built, just skip them
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/RpcProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/RpcProcessor.cs
index 9c2f2f6..a2b042b 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/RpcProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/RpcProcessor.cs
@@ -1,37 +1,38 @@
-// all the [Rpc] code from NetworkBehaviourProcessor in one place
using Mono.CecilX;
using Mono.CecilX.Cil;
+
namespace Mirror.Weaver
{
+ ///
+ /// Processes [Rpc] methods in NetworkBehaviour
+ ///
public static class RpcProcessor
{
- public const string RpcPrefix = "InvokeRpc";
-
public static MethodDefinition ProcessRpcInvoke(TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc)
{
MethodDefinition rpc = new MethodDefinition(
- RpcPrefix + md.Name,
+ Weaver.InvokeRpcPrefix + md.Name,
MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig,
Weaver.voidType);
- ILProcessor rpcWorker = rpc.Body.GetILProcessor();
- Instruction label = rpcWorker.Create(OpCodes.Nop);
+ ILProcessor worker = rpc.Body.GetILProcessor();
+ Instruction label = worker.Create(OpCodes.Nop);
- NetworkBehaviourProcessor.WriteClientActiveCheck(rpcWorker, md.Name, label, "RPC");
+ NetworkBehaviourProcessor.WriteClientActiveCheck(worker, md.Name, label, "RPC");
// setup for reader
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0));
- rpcWorker.Append(rpcWorker.Create(OpCodes.Castclass, td));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Castclass, td));
- if (!NetworkBehaviourProcessor.ProcessNetworkReaderParameters(md, rpcWorker, false))
+ if (!NetworkBehaviourProcessor.ReadArguments(md, worker, RemoteCallType.ClientRpc))
return null;
// invoke actual command function
- rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, rpcCallFunc));
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Callvirt, rpcCallFunc));
+ worker.Append(worker.Create(OpCodes.Ret));
NetworkBehaviourProcessor.AddInvokeParameters(rpc.Parameters);
-
+ td.Methods.Add(rpc);
return rpc;
}
@@ -52,78 +53,66 @@ public void CallRpcTest (int param)
Originally HLAPI put the send message code inside the Call function
and then proceeded to replace every call to RpcTest with CallRpcTest
- This method moves all the user's code into the "Call" method
+ This method moves all the user's code into the "CallRpc" method
and replaces the body of the original method with the send message code.
This way we do not need to modify the code anywhere else, and this works
correctly in dependent assemblies
*/
- public static MethodDefinition ProcessRpcCall(TypeDefinition td, MethodDefinition md, CustomAttribute ca)
+ public static MethodDefinition ProcessRpcCall(TypeDefinition td, MethodDefinition md, CustomAttribute clientRpcAttr)
{
- MethodDefinition rpc = new MethodDefinition("Call" + md.Name, MethodAttributes.Public |
- MethodAttributes.HideBySig,
- Weaver.voidType);
-
- // add paramters
- foreach (ParameterDefinition pd in md.Parameters)
- {
- rpc.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
- }
+ MethodDefinition rpc = MethodProcessor.SubstituteMethod(td, md);
- // move the old body to the new function
- MethodBody newBody = rpc.Body;
- rpc.Body = md.Body;
- md.Body = newBody;
+ ILProcessor worker = md.Body.GetILProcessor();
- ILProcessor rpcWorker = md.Body.GetILProcessor();
+ NetworkBehaviourProcessor.WriteSetupLocals(worker);
- NetworkBehaviourProcessor.WriteSetupLocals(rpcWorker);
+ if (Weaver.GenerateLogErrors)
+ {
+ worker.Append(worker.Create(OpCodes.Ldstr, "Call ClientRpc function " + md.Name));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.logErrorReference));
+ }
- NetworkBehaviourProcessor.WriteCreateWriter(rpcWorker);
+ NetworkBehaviourProcessor.WriteCreateWriter(worker);
// write all the arguments that the user passed to the Rpc call
- if (!NetworkBehaviourProcessor.WriteArguments(rpcWorker, md, false))
+ if (!NetworkBehaviourProcessor.WriteArguments(worker, md, RemoteCallType.ClientRpc))
return null;
string rpcName = md.Name;
- int index = rpcName.IndexOf(RpcPrefix);
- if (index > -1)
- {
- rpcName = rpcName.Substring(RpcPrefix.Length);
- }
+ int channel = clientRpcAttr.GetField("channel", 0);
+ bool excludeOwner = clientRpcAttr.GetField("excludeOwner", false);
// invoke SendInternal and return
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); // this
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldtoken, td));
- rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); // invokerClass
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName));
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0)); // writer
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
- rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendRpcInternal));
-
- NetworkBehaviourProcessor.WriteRecycleWriter(rpcWorker);
-
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));
+ // this
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldtoken, td));
+ // invokerClass
+ worker.Append(worker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference));
+ worker.Append(worker.Create(OpCodes.Ldstr, rpcName));
+ // writer
+ worker.Append(worker.Create(OpCodes.Ldloc_0));
+ worker.Append(worker.Create(OpCodes.Ldc_I4, channel));
+ worker.Append(worker.Create(excludeOwner ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0));
+ worker.Append(worker.Create(OpCodes.Callvirt, Weaver.sendRpcInternal));
+
+ NetworkBehaviourProcessor.WriteRecycleWriter(worker);
+
+ worker.Append(worker.Create(OpCodes.Ret));
return rpc;
}
- public static bool ProcessMethodsValidateRpc(MethodDefinition md, CustomAttribute ca)
+ public static bool ProcessMethodsValidateRpc(MethodDefinition md)
{
- if (!md.Name.StartsWith("Rpc"))
- {
- Weaver.Error($"{md} must start with Rpc. Consider renaming it to Rpc{md.Name}");
- return false;
- }
-
if (md.IsStatic)
{
- Weaver.Error($"{md} must not be static");
+ Weaver.Error($"{md.Name} must not be static", md);
return false;
}
// validate
return NetworkBehaviourProcessor.ProcessMethodsValidateFunction(md) &&
- NetworkBehaviourProcessor.ProcessMethodsValidateParameters(md, ca);
+ NetworkBehaviourProcessor.ProcessMethodsValidateParameters(md, RemoteCallType.ClientRpc);
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs
new file mode 100644
index 0000000..0600b04
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs
@@ -0,0 +1,132 @@
+using Mono.CecilX;
+using Mono.CecilX.Cil;
+
+namespace Mirror.Weaver
+{
+ ///
+ /// processes SyncVars, Cmds, Rpcs, etc. of NetworkBehaviours
+ ///
+ static class ServerClientAttributeProcessor
+ {
+ public static void ProcessMethodAttributes(TypeDefinition td, MethodDefinition md)
+ {
+ foreach (CustomAttribute attr in md.CustomAttributes)
+ {
+ switch (attr.Constructor.DeclaringType.ToString())
+ {
+ case "Mirror.ServerAttribute":
+ InjectServerGuard(td, md, true);
+ break;
+ case "Mirror.ServerCallbackAttribute":
+ InjectServerGuard(td, md, false);
+ break;
+ case "Mirror.ClientAttribute":
+ InjectClientGuard(td, md, true);
+ break;
+ case "Mirror.ClientCallbackAttribute":
+ InjectClientGuard(td, md, false);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ static void InjectServerGuard(TypeDefinition td, MethodDefinition md, bool logWarning)
+ {
+ if (!Weaver.IsNetworkBehaviour(td))
+ {
+ Weaver.Error($"Server method {md.Name} must be declared in a NetworkBehaviour", md);
+ return;
+ }
+ ILProcessor worker = md.Body.GetILProcessor();
+ Instruction top = md.Body.Instructions[0];
+
+ worker.InsertBefore(top, worker.Create(OpCodes.Call, Weaver.NetworkServerGetActive));
+ worker.InsertBefore(top, worker.Create(OpCodes.Brtrue, top));
+ if (logWarning)
+ {
+ worker.InsertBefore(top, worker.Create(OpCodes.Ldstr, "[Server] function '" + md.FullName + "' called on client"));
+ worker.InsertBefore(top, worker.Create(OpCodes.Call, Weaver.logWarningReference));
+ }
+ InjectGuardParameters(md, worker, top);
+ InjectGuardReturnValue(md, worker, top);
+ worker.InsertBefore(top, worker.Create(OpCodes.Ret));
+ }
+
+ static void InjectClientGuard(TypeDefinition td, MethodDefinition md, bool logWarning)
+ {
+ if (!Weaver.IsNetworkBehaviour(td))
+ {
+ Weaver.Error($"Client method {md.Name} must be declared in a NetworkBehaviour", md);
+ return;
+ }
+ ILProcessor worker = md.Body.GetILProcessor();
+ Instruction top = md.Body.Instructions[0];
+
+ worker.InsertBefore(top, worker.Create(OpCodes.Call, Weaver.NetworkClientGetActive));
+ worker.InsertBefore(top, worker.Create(OpCodes.Brtrue, top));
+ if (logWarning)
+ {
+ worker.InsertBefore(top, worker.Create(OpCodes.Ldstr, "[Client] function '" + md.FullName + "' called on server"));
+ worker.InsertBefore(top, worker.Create(OpCodes.Call, Weaver.logWarningReference));
+ }
+
+ InjectGuardParameters(md, worker, top);
+ InjectGuardReturnValue(md, worker, top);
+ worker.InsertBefore(top, worker.Create(OpCodes.Ret));
+ }
+
+ // this is required to early-out from a function with "ref" or "out" parameters
+ static void InjectGuardParameters(MethodDefinition md, ILProcessor worker, Instruction top)
+ {
+ int offset = md.Resolve().IsStatic ? 0 : 1;
+ for (int index = 0; index < md.Parameters.Count; index++)
+ {
+ ParameterDefinition param = md.Parameters[index];
+ if (param.IsOut)
+ {
+ TypeReference elementType = param.ParameterType.GetElementType();
+ if (elementType.IsPrimitive)
+ {
+ worker.InsertBefore(top, worker.Create(OpCodes.Ldarg, index + offset));
+ worker.InsertBefore(top, worker.Create(OpCodes.Ldc_I4_0));
+ worker.InsertBefore(top, worker.Create(OpCodes.Stind_I4));
+ }
+ else
+ {
+ md.Body.Variables.Add(new VariableDefinition(elementType));
+ md.Body.InitLocals = true;
+
+ worker.InsertBefore(top, worker.Create(OpCodes.Ldarg, index + offset));
+ worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, (byte)(md.Body.Variables.Count - 1)));
+ worker.InsertBefore(top, worker.Create(OpCodes.Initobj, elementType));
+ worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, md.Body.Variables.Count - 1));
+ worker.InsertBefore(top, worker.Create(OpCodes.Stobj, elementType));
+ }
+ }
+ }
+ }
+
+ // this is required to early-out from a function with a return value.
+ static void InjectGuardReturnValue(MethodDefinition md, ILProcessor worker, Instruction top)
+ {
+ if (md.ReturnType.FullName != Weaver.voidType.FullName)
+ {
+ if (md.ReturnType.IsPrimitive)
+ {
+ worker.InsertBefore(top, worker.Create(OpCodes.Ldc_I4_0));
+ }
+ else
+ {
+ md.Body.Variables.Add(new VariableDefinition(md.ReturnType));
+ md.Body.InitLocals = true;
+
+ worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, (byte)(md.Body.Variables.Count - 1)));
+ worker.InsertBefore(top, worker.Create(OpCodes.Initobj, md.ReturnType));
+ worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, md.Body.Variables.Count - 1));
+ }
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs.meta
new file mode 100644
index 0000000..5a5451d
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/ServerClientAttributeProcessor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 024f251bf693bb345b90b9177892d534
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncDictionaryProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncDictionaryProcessor.cs
index a095967..e5acd68 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncDictionaryProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncDictionaryProcessor.cs
@@ -1,9 +1,10 @@
-// this class generates OnSerialize/OnDeserialize for SyncLists
using Mono.CecilX;
-using Mono.CecilX.Cil;
namespace Mirror.Weaver
{
+ ///
+ /// generates OnSerialize/OnDeserialize for SyncLists
+ ///
static class SyncDictionaryProcessor
{
///
@@ -12,8 +13,26 @@ static class SyncDictionaryProcessor
/// The synclist class
public static void Process(TypeDefinition td)
{
- SyncObjectProcessor.GenerateSerialization(td, 0, "SerializeKey", "DeserializeKey");
- SyncObjectProcessor.GenerateSerialization(td, 1, "SerializeItem", "DeserializeItem");
+ GenericArgumentResolver resolver = new GenericArgumentResolver(2);
+
+ if (resolver.GetGenericFromBaseClass(td, 0, Weaver.SyncDictionaryType, out TypeReference keyType))
+ {
+ SyncObjectProcessor.GenerateSerialization(td, keyType, Weaver.SyncDictionaryType, "SerializeKey", "DeserializeKey");
+ }
+ else
+ {
+ Weaver.Error($"Could not find generic arguments for SyncDictionary in {td.Name}", td);
+ return;
+ }
+
+ if (resolver.GetGenericFromBaseClass(td, 1, Weaver.SyncDictionaryType, out TypeReference itemType))
+ {
+ SyncObjectProcessor.GenerateSerialization(td, itemType, Weaver.SyncDictionaryType, "SerializeItem", "DeserializeItem");
+ }
+ else
+ {
+ Weaver.Error($"Could not find generic arguments for SyncDictionary in {td.Name}", td);
+ }
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs
index 3a4e36f..10fc7e6 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs
@@ -1,10 +1,12 @@
-// all the SyncEvent code from NetworkBehaviourProcessor in one place
using System.Collections.Generic;
using Mono.CecilX;
using Mono.CecilX.Cil;
namespace Mirror.Weaver
{
+ ///
+ /// Processes SyncEvents in NetworkBehaviour
+ ///
public static class SyncEventProcessor
{
public static MethodDefinition ProcessEventInvoke(TypeDefinition td, EventDefinition ed)
@@ -21,52 +23,52 @@ public static MethodDefinition ProcessEventInvoke(TypeDefinition td, EventDefini
}
if (eventField == null)
{
- Weaver.Error($"{td} not found. Did you declare the event?");
+ Weaver.Error($"event field not found for {ed.Name}. Did you declare it as an event?", ed);
return null;
}
- MethodDefinition cmd = new MethodDefinition("InvokeSyncEvent" + ed.Name, MethodAttributes.Family |
+ MethodDefinition cmd = new MethodDefinition(Weaver.InvokeRpcPrefix + ed.Name, MethodAttributes.Family |
MethodAttributes.Static |
MethodAttributes.HideBySig,
Weaver.voidType);
- ILProcessor cmdWorker = cmd.Body.GetILProcessor();
- Instruction label1 = cmdWorker.Create(OpCodes.Nop);
- Instruction label2 = cmdWorker.Create(OpCodes.Nop);
+ ILProcessor worker = cmd.Body.GetILProcessor();
+ Instruction label1 = worker.Create(OpCodes.Nop);
+ Instruction label2 = worker.Create(OpCodes.Nop);
- NetworkBehaviourProcessor.WriteClientActiveCheck(cmdWorker, ed.Name, label1, "Event");
+ NetworkBehaviourProcessor.WriteClientActiveCheck(worker, ed.Name, label1, "Event");
// null event check
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Castclass, td));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldfld, eventField));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Brtrue, label2));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ret));
- cmdWorker.Append(label2);
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Castclass, td));
+ worker.Append(worker.Create(OpCodes.Ldfld, eventField));
+ worker.Append(worker.Create(OpCodes.Brtrue, label2));
+ worker.Append(worker.Create(OpCodes.Ret));
+ worker.Append(label2);
// setup reader
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Castclass, td));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ldfld, eventField));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Castclass, td));
+ worker.Append(worker.Create(OpCodes.Ldfld, eventField));
// read the event arguments
MethodReference invoke = Resolvers.ResolveMethod(eventField.FieldType, Weaver.CurrentAssembly, "Invoke");
- if (!NetworkBehaviourProcessor.ProcessNetworkReaderParameters(invoke.Resolve(), cmdWorker, false))
+ if (!NetworkBehaviourProcessor.ReadArguments(invoke.Resolve(), worker, RemoteCallType.SyncEvent))
return null;
// invoke actual event delegate function
- cmdWorker.Append(cmdWorker.Create(OpCodes.Callvirt, invoke));
- cmdWorker.Append(cmdWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Callvirt, invoke));
+ worker.Append(worker.Create(OpCodes.Ret));
NetworkBehaviourProcessor.AddInvokeParameters(cmd.Parameters);
return cmd;
}
- public static MethodDefinition ProcessEventCall(TypeDefinition td, EventDefinition ed, CustomAttribute ca)
+ public static MethodDefinition ProcessEventCall(TypeDefinition td, EventDefinition ed, CustomAttribute syncEventAttr)
{
MethodReference invoke = Resolvers.ResolveMethod(ed.EventType, Weaver.CurrentAssembly, "Invoke");
- MethodDefinition evt = new MethodDefinition("Call" + ed.Name, MethodAttributes.Public |
+ MethodDefinition evt = new MethodDefinition(Weaver.SyncEventPrefix + ed.Name, MethodAttributes.Public |
MethodAttributes.HideBySig,
Weaver.voidType);
// add paramters
@@ -75,31 +77,34 @@ public static MethodDefinition ProcessEventCall(TypeDefinition td, EventDefiniti
evt.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
}
- ILProcessor evtWorker = evt.Body.GetILProcessor();
- Instruction label = evtWorker.Create(OpCodes.Nop);
+ ILProcessor worker = evt.Body.GetILProcessor();
+ Instruction label = worker.Create(OpCodes.Nop);
- NetworkBehaviourProcessor.WriteSetupLocals(evtWorker);
+ NetworkBehaviourProcessor.WriteSetupLocals(worker);
- NetworkBehaviourProcessor.WriteServerActiveCheck(evtWorker, ed.Name, label, "Event");
+ NetworkBehaviourProcessor.WriteServerActiveCheck(worker, ed.Name, label, "Event");
- NetworkBehaviourProcessor.WriteCreateWriter(evtWorker);
+ NetworkBehaviourProcessor.WriteCreateWriter(worker);
// write all the arguments that the user passed to the syncevent
- if (!NetworkBehaviourProcessor.WriteArguments(evtWorker, invoke.Resolve(), false))
+ if (!NetworkBehaviourProcessor.WriteArguments(worker, invoke.Resolve(), RemoteCallType.SyncEvent))
return null;
// invoke interal send and return
- evtWorker.Append(evtWorker.Create(OpCodes.Ldarg_0)); // this
- evtWorker.Append(evtWorker.Create(OpCodes.Ldtoken, td));
- evtWorker.Append(evtWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); // invokerClass
- evtWorker.Append(evtWorker.Create(OpCodes.Ldstr, ed.Name));
- evtWorker.Append(evtWorker.Create(OpCodes.Ldloc_0)); // writer
- evtWorker.Append(evtWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
- evtWorker.Append(evtWorker.Create(OpCodes.Call, Weaver.sendEventInternal));
+ // this
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldtoken, td));
+ // invokerClass
+ worker.Append(worker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference));
+ worker.Append(worker.Create(OpCodes.Ldstr, ed.Name));
+ // writer
+ worker.Append(worker.Create(OpCodes.Ldloc_0));
+ worker.Append(worker.Create(OpCodes.Ldc_I4, syncEventAttr.GetField("channel", 0)));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.sendEventInternal));
- NetworkBehaviourProcessor.WriteRecycleWriter(evtWorker);
+ NetworkBehaviourProcessor.WriteRecycleWriter(worker);
- evtWorker.Append(evtWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Ret));
return evt;
}
@@ -109,42 +114,35 @@ public static void ProcessEvents(TypeDefinition td, List events
// find events
foreach (EventDefinition ed in td.Events)
{
- foreach (CustomAttribute ca in ed.CustomAttributes)
+ CustomAttribute syncEventAttr = ed.GetCustomAttribute(Weaver.SyncEventType.FullName);
+
+ if (syncEventAttr != null)
{
- if (ca.AttributeType.FullName == Weaver.SyncEventType.FullName)
+ if (ed.EventType.Resolve().HasGenericParameters)
{
- if (!ed.Name.StartsWith("Event"))
- {
- Weaver.Error($"{ed} must start with Event. Consider renaming it to Event{ed.Name}");
- return;
- }
-
- if (ed.EventType.Resolve().HasGenericParameters)
- {
- Weaver.Error($"{ed} must not have generic parameters. Consider creating a new class that inherits from {ed.EventType} instead");
- return;
- }
+ Weaver.Error($"{ed.Name} must not have generic parameters. Consider creating a new class that inherits from {ed.EventType} instead", ed);
+ return;
+ }
- events.Add(ed);
- MethodDefinition eventFunc = ProcessEventInvoke(td, ed);
- if (eventFunc == null)
- {
- return;
- }
+ events.Add(ed);
+ MethodDefinition eventFunc = ProcessEventInvoke(td, ed);
+ if (eventFunc == null)
+ {
+ return;
+ }
- td.Methods.Add(eventFunc);
- eventInvocationFuncs.Add(eventFunc);
+ td.Methods.Add(eventFunc);
+ eventInvocationFuncs.Add(eventFunc);
- Weaver.DLog(td, "ProcessEvent " + ed);
+ Weaver.DLog(td, "ProcessEvent " + ed);
- MethodDefinition eventCallFunc = ProcessEventCall(td, ed, ca);
- td.Methods.Add(eventCallFunc);
+ MethodDefinition eventCallFunc = ProcessEventCall(td, ed, syncEventAttr);
+ td.Methods.Add(eventCallFunc);
- Weaver.WeaveLists.replaceEvents[ed.Name] = eventCallFunc; // original weaver compares .Name, not EventDefinition.
+ // original weaver compares .Name, not EventDefinition.
+ Weaver.WeaveLists.replaceEvents[ed.FullName] = eventCallFunc;
- Weaver.DLog(td, " Event: " + ed.Name);
- break;
- }
+ Weaver.DLog(td, " Event: " + ed.Name);
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListInitializer.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListInitializer.cs
deleted file mode 100644
index 20db50b..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListInitializer.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-// This file was removed in Mirror 3.4.9
-// The purpose of this file is to get the old file overwritten
-// when users update from the asset store to prevent a flood of errors
-// from having the old file still in the project as a straggler.
-// This file will be dropped from the Asset Store package in May 2019
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListProcessor.cs
index 0da1746..67af00e 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListProcessor.cs
@@ -1,18 +1,29 @@
-// this class generates OnSerialize/OnDeserialize for SyncLists
using Mono.CecilX;
-using Mono.CecilX.Cil;
namespace Mirror.Weaver
{
+ ///
+ /// generates OnSerialize/OnDeserialize for SyncLists
+ ///
static class SyncListProcessor
{
///
/// Generates serialization methods for synclists
///
/// The synclist class
- public static void Process(TypeDefinition td)
+ /// the base SyncObject td inherits from
+ public static void Process(TypeDefinition td, TypeReference mirrorBaseType)
{
- SyncObjectProcessor.GenerateSerialization(td, 0, "SerializeItem", "DeserializeItem");
+ GenericArgumentResolver resolver = new GenericArgumentResolver(1);
+
+ if (resolver.GetGenericFromBaseClass(td, 0, mirrorBaseType, out TypeReference itemType))
+ {
+ SyncObjectProcessor.GenerateSerialization(td, itemType, mirrorBaseType, "SerializeItem", "DeserializeItem");
+ }
+ else
+ {
+ Weaver.Error($"Could not find generic arguments for {mirrorBaseType.Name} in {td}", td);
+ }
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListStructProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListStructProcessor.cs
deleted file mode 100644
index 20db50b..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListStructProcessor.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-// This file was removed in Mirror 3.4.9
-// The purpose of this file is to get the old file overwritten
-// when users update from the asset store to prevent a flood of errors
-// from having the old file still in the project as a straggler.
-// This file will be dropped from the Asset Store package in May 2019
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListStructProcessor.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListStructProcessor.cs.meta
deleted file mode 100644
index 8f234cd..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncListStructProcessor.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 28fb192f6a9bc1247b90aa4710f6d34f
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncObjectInitializer.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncObjectInitializer.cs
index 14e27f6..fd38659 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncObjectInitializer.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncObjectInitializer.cs
@@ -1,5 +1,3 @@
-// SyncObject code
-using System;
using System.Linq;
using Mono.CecilX;
using Mono.CecilX.Cil;
@@ -8,20 +6,20 @@ namespace Mirror.Weaver
{
public static class SyncObjectInitializer
{
- public static void GenerateSyncObjectInitializer(ILProcessor methodWorker, FieldDefinition fd)
+ public static void GenerateSyncObjectInitializer(ILProcessor worker, FieldDefinition fd)
{
// call syncobject constructor
- GenerateSyncObjectInstanceInitializer(methodWorker, fd);
+ GenerateSyncObjectInstanceInitializer(worker, fd);
// register syncobject in network behaviour
- GenerateSyncObjectRegistration(methodWorker, fd);
+ GenerateSyncObjectRegistration(worker, fd);
}
// generates 'syncListInt = new SyncListInt()' if user didn't do that yet
- static void GenerateSyncObjectInstanceInitializer(ILProcessor ctorWorker, FieldDefinition fd)
+ static void GenerateSyncObjectInstanceInitializer(ILProcessor worker, FieldDefinition fd)
{
// check the ctor's instructions for an Stfld op-code for this specific sync list field.
- foreach (Instruction ins in ctorWorker.Body.Instructions)
+ foreach (Instruction ins in worker.Body.Instructions)
{
if (ins.OpCode.Code == Code.Stfld)
{
@@ -37,20 +35,20 @@ static void GenerateSyncObjectInstanceInitializer(ILProcessor ctorWorker, FieldD
// Not initialized by the user in the field definition, e.g:
// public SyncListInt Foo;
- MethodReference objectConstructor;
- try
- {
- objectConstructor = Weaver.CurrentAssembly.MainModule.ImportReference(fd.FieldType.Resolve().Methods.First(x => x.Name == ".ctor" && !x.HasParameters));
- }
- catch (Exception)
+
+ TypeDefinition fieldType = fd.FieldType.Resolve();
+ // find ctor with no parameters
+ MethodDefinition ctor = fieldType.Methods.FirstOrDefault(x => x.Name == ".ctor" && !x.HasParameters);
+ if (ctor == null)
{
- Weaver.Error($"{fd} does not have a default constructor");
+ Weaver.Error($"Can not initialize field {fd.Name} because no default constructor was found. Manually initialize the field (call the constructor) or add constructor without Parameter", fd);
return;
}
+ MethodReference objectConstructor = Weaver.CurrentAssembly.MainModule.ImportReference(ctor);
- ctorWorker.Append(ctorWorker.Create(OpCodes.Ldarg_0));
- ctorWorker.Append(ctorWorker.Create(OpCodes.Newobj, objectConstructor));
- ctorWorker.Append(ctorWorker.Create(OpCodes.Stfld, fd));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Newobj, objectConstructor));
+ worker.Append(worker.Create(OpCodes.Stfld, fd));
}
public static bool ImplementsSyncObject(TypeReference typeRef)
@@ -77,13 +75,13 @@ public static bool ImplementsSyncObject(TypeReference typeRef)
// generates code like:
this.InitSyncObject(m_sizes);
*/
- static void GenerateSyncObjectRegistration(ILProcessor methodWorker, FieldDefinition fd)
+ static void GenerateSyncObjectRegistration(ILProcessor worker, FieldDefinition fd)
{
- methodWorker.Append(methodWorker.Create(OpCodes.Ldarg_0));
- methodWorker.Append(methodWorker.Create(OpCodes.Ldarg_0));
- methodWorker.Append(methodWorker.Create(OpCodes.Ldfld, fd));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, fd));
- methodWorker.Append(methodWorker.Create(OpCodes.Call, Weaver.InitSyncObjectReference));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.InitSyncObjectReference));
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs
index 9eb7494..f4e239c 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs
@@ -1,4 +1,3 @@
-using System;
using Mono.CecilX;
using Mono.CecilX.Cil;
@@ -10,44 +9,41 @@ public static class SyncObjectProcessor
/// Generates the serialization and deserialization methods for a specified generic argument
///
/// The type of the class that needs serialization methods
- /// Which generic argument to serialize, 0 is the first one
+ /// generic argument to serialize
+ /// the base SyncObject td inherits from
/// The name of the serialize method
/// The name of the deserialize method
- public static void GenerateSerialization(TypeDefinition td, int genericArgument, string serializeMethod, string deserializeMethod)
+ public static void GenerateSerialization(TypeDefinition td, TypeReference itemType, TypeReference mirrorBaseType, string serializeMethod, string deserializeMethod)
{
- // find item type
- GenericInstanceType gt = (GenericInstanceType)td.BaseType;
- if (gt.GenericArguments.Count <= genericArgument)
- {
- Weaver.Error($"{td} should have {genericArgument} generic arguments");
- return;
- }
- TypeReference itemType = Weaver.CurrentAssembly.MainModule.ImportReference(gt.GenericArguments[genericArgument]);
-
Weaver.DLog(td, "SyncObjectProcessor Start item:" + itemType.FullName);
- MethodReference writeItemFunc = GenerateSerialization(serializeMethod, td, itemType);
+ bool success = GenerateSerialization(serializeMethod, td, itemType, mirrorBaseType);
if (Weaver.WeavingFailed)
{
return;
}
- MethodReference readItemFunc = GenerateDeserialization(deserializeMethod, td, itemType);
+ success |= GenerateDeserialization(deserializeMethod, td, itemType, mirrorBaseType);
- if (readItemFunc == null || writeItemFunc == null)
- return;
-
- Weaver.DLog(td, "SyncObjectProcessor Done");
+ if (success)
+ Weaver.DLog(td, "SyncObjectProcessor Done");
}
// serialization of individual element
- static MethodReference GenerateSerialization(string methodName, TypeDefinition td, TypeReference itemType)
+ static bool GenerateSerialization(string methodName, TypeDefinition td, TypeReference itemType, TypeReference mirrorBaseType)
{
Weaver.DLog(td, " GenerateSerialization");
- foreach (MethodDefinition m in td.Methods)
+ bool existing = td.HasMethodInBaseType(methodName, mirrorBaseType);
+ if (existing)
+ return true;
+
+
+ // this check needs to happen inside GenerateSerialization because
+ // we need to check if user has made custom function above
+ if (itemType.IsGenericInstance)
{
- if (m.Name == methodName)
- return m;
+ Weaver.Error($"Can not create Serialize or Deserialize for generic element in {td.Name}. Override virtual methods with custom Serialize and Deserialize to use {itemType} in SyncList", td);
+ return false;
}
MethodDefinition serializeFunc = new MethodDefinition(methodName, MethodAttributes.Public |
@@ -58,39 +54,39 @@ static MethodReference GenerateSerialization(string methodName, TypeDefinition t
serializeFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkWriterType)));
serializeFunc.Parameters.Add(new ParameterDefinition("item", ParameterAttributes.None, itemType));
- ILProcessor serWorker = serializeFunc.Body.GetILProcessor();
-
- if (itemType.IsGenericInstance)
- {
- Weaver.Error($"{td} cannot have generic elements {itemType}");
- return null;
- }
+ ILProcessor worker = serializeFunc.Body.GetILProcessor();
MethodReference writeFunc = Writers.GetWriteFunc(itemType);
if (writeFunc != null)
{
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
- serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ worker.Append(worker.Create(OpCodes.Ldarg_2));
+ worker.Append(worker.Create(OpCodes.Call, writeFunc));
}
else
{
- Weaver.Error($"{td} cannot have item of type {itemType}. Use a type supported by mirror instead");
- return null;
+ Weaver.Error($"{td.Name} has sync object generic type {itemType.Name}. Use a type supported by mirror instead", td);
+ return false;
}
- serWorker.Append(serWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Ret));
td.Methods.Add(serializeFunc);
- return serializeFunc;
+ return true;
}
- static MethodReference GenerateDeserialization(string methodName, TypeDefinition td, TypeReference itemType)
+ static bool GenerateDeserialization(string methodName, TypeDefinition td, TypeReference itemType, TypeReference mirrorBaseType)
{
Weaver.DLog(td, " GenerateDeserialization");
- foreach (MethodDefinition m in td.Methods)
+ bool existing = td.HasMethodInBaseType(methodName, mirrorBaseType);
+ if (existing)
+ return true;
+
+ // this check needs to happen inside GenerateDeserialization because
+ // we need to check if user has made custom function above
+ if (itemType.IsGenericInstance)
{
- if (m.Name == methodName)
- return m;
+ Weaver.Error($"Can not create Serialize or Deserialize for generic element in {td.Name}. Override virtual methods with custom Serialize and Deserialize to use {itemType.Name} in SyncList", td);
+ return false;
}
MethodDefinition deserializeFunction = new MethodDefinition(methodName, MethodAttributes.Public |
@@ -101,23 +97,23 @@ static MethodReference GenerateDeserialization(string methodName, TypeDefinition
deserializeFunction.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
- ILProcessor serWorker = deserializeFunction.Body.GetILProcessor();
+ ILProcessor worker = deserializeFunction.Body.GetILProcessor();
MethodReference readerFunc = Readers.GetReadFunc(itemType);
if (readerFunc != null)
{
- serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
- serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc));
- serWorker.Append(serWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ worker.Append(worker.Create(OpCodes.Call, readerFunc));
+ worker.Append(worker.Create(OpCodes.Ret));
}
else
{
- Weaver.Error($"{td} cannot have item of type {itemType}. Use a type supported by mirror instead");
- return null;
+ Weaver.Error($"{td.Name} has sync object generic type {itemType.Name}. Use a type supported by mirror instead", td);
+ return false;
}
td.Methods.Add(deserializeFunction);
- return deserializeFunction;
+ return true;
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncVarProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncVarProcessor.cs
index 86be11c..6d4f1a0 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncVarProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/SyncVarProcessor.cs
@@ -1,53 +1,73 @@
-// all the [SyncVar] code from NetworkBehaviourProcessor in one place
using System.Collections.Generic;
+using System.Linq;
using Mono.CecilX;
using Mono.CecilX.Cil;
namespace Mirror.Weaver
{
+ ///
+ /// Processes [SyncVar] in NetworkBehaviour
+ ///
public static class SyncVarProcessor
{
- const int SyncVarLimit = 64; // ulong = 64 bytes
+ // ulong = 64 bytes
+ const int SyncVarLimit = 64;
- // returns false for error, not for no-hook-exists
- public static bool CheckForHookFunction(TypeDefinition td, FieldDefinition syncVar, out MethodDefinition foundMethod)
+
+ static string HookParameterMessage(string hookName, TypeReference ValueType)
+ => string.Format("void {0}({1} oldValue, {1} newValue)", hookName, ValueType);
+
+ // Get hook method if any
+ public static MethodDefinition GetHookMethod(TypeDefinition td, FieldDefinition syncVar)
+ {
+ CustomAttribute syncVarAttr = syncVar.GetCustomAttribute(Weaver.SyncVarType.FullName);
+
+ if (syncVarAttr == null)
+ return null;
+
+ string hookFunctionName = syncVarAttr.GetField("hook", null);
+
+ if (hookFunctionName == null)
+ return null;
+
+ return FindHookMethod(td, syncVar, hookFunctionName);
+ }
+
+ static MethodDefinition FindHookMethod(TypeDefinition td, FieldDefinition syncVar, string hookFunctionName)
{
- foundMethod = null;
- foreach (CustomAttribute ca in syncVar.CustomAttributes)
+ List methods = td.GetMethods(hookFunctionName);
+
+ List methodsWith2Param = new List(methods.Where(m => m.Parameters.Count == 2));
+
+ if (methodsWith2Param.Count == 0)
+ {
+ Weaver.Error($"Could not find hook for '{syncVar.Name}', hook name '{hookFunctionName}'. " +
+ $"Method signature should be {HookParameterMessage(hookFunctionName, syncVar.FieldType)}",
+ syncVar);
+
+ return null;
+ }
+
+ foreach (MethodDefinition method in methodsWith2Param)
{
- if (ca.AttributeType.FullName == Weaver.SyncVarType.FullName)
+ if (MatchesParameters(syncVar, method))
{
- foreach (CustomAttributeNamedArgument customField in ca.Fields)
- {
- if (customField.Name == "hook")
- {
- string hookFunctionName = customField.Argument.Value as string;
-
- foreach (MethodDefinition m in td.Methods)
- {
- if (m.Name == hookFunctionName)
- {
- if (m.Parameters.Count == 1)
- {
- if (m.Parameters[0].ParameterType != syncVar.FieldType)
- {
- Weaver.Error($"{m} should have signature:\npublic void {hookFunctionName}({syncVar.FieldType} value) {{ }}");
- return false;
- }
- foundMethod = m;
- return true;
- }
- Weaver.Error($"{m} should have signature:\npublic void {hookFunctionName}({syncVar.FieldType} value) {{ }}");
- return false;
- }
- }
- Weaver.Error($"No hook implementation found for {syncVar}. Add this method to your class:\npublic void {hookFunctionName}({syncVar.FieldType} value) {{ }}" );
- return false;
- }
- }
+ return method;
}
}
- return true;
+
+ Weaver.Error($"Wrong type for Parameter in hook for '{syncVar.Name}', hook name '{hookFunctionName}'. " +
+ $"Method signature should be {HookParameterMessage(hookFunctionName, syncVar.FieldType)}",
+ syncVar);
+
+ return null;
+ }
+
+ static bool MatchesParameters(FieldDefinition syncVar, MethodDefinition method)
+ {
+ // matches void onValueChange(T oldValue, T newValue)
+ return method.Parameters[0].ParameterType.FullName == syncVar.FieldType.FullName &&
+ method.Parameters[1].ParameterType.FullName == syncVar.FieldType.FullName;
}
public static MethodDefinition ProcessSyncVarGet(FieldDefinition fd, string originalName, FieldDefinition netFieldId)
@@ -59,38 +79,40 @@ public static MethodDefinition ProcessSyncVarGet(FieldDefinition fd, string orig
MethodAttributes.HideBySig,
fd.FieldType);
- ILProcessor getWorker = get.Body.GetILProcessor();
+ ILProcessor worker = get.Body.GetILProcessor();
// [SyncVar] GameObject?
if (fd.FieldType.FullName == Weaver.gameObjectType.FullName)
{
// return this.GetSyncVarGameObject(ref field, uint netId);
- getWorker.Append(getWorker.Create(OpCodes.Ldarg_0)); // this.
- getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
- getWorker.Append(getWorker.Create(OpCodes.Ldfld, netFieldId));
- getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
- getWorker.Append(getWorker.Create(OpCodes.Ldflda, fd));
- getWorker.Append(getWorker.Create(OpCodes.Call, Weaver.getSyncVarGameObjectReference));
- getWorker.Append(getWorker.Create(OpCodes.Ret));
+ // this.
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldflda, fd));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.getSyncVarGameObjectReference));
+ worker.Append(worker.Create(OpCodes.Ret));
}
// [SyncVar] NetworkIdentity?
else if (fd.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
{
// return this.GetSyncVarNetworkIdentity(ref field, uint netId);
- getWorker.Append(getWorker.Create(OpCodes.Ldarg_0)); // this.
- getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
- getWorker.Append(getWorker.Create(OpCodes.Ldfld, netFieldId));
- getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
- getWorker.Append(getWorker.Create(OpCodes.Ldflda, fd));
- getWorker.Append(getWorker.Create(OpCodes.Call, Weaver.getSyncVarNetworkIdentityReference));
- getWorker.Append(getWorker.Create(OpCodes.Ret));
+ // this.
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldflda, fd));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.getSyncVarNetworkIdentityReference));
+ worker.Append(worker.Create(OpCodes.Ret));
}
// [SyncVar] int, string, etc.
else
{
- getWorker.Append(getWorker.Create(OpCodes.Ldarg_0));
- getWorker.Append(getWorker.Create(OpCodes.Ldfld, fd));
- getWorker.Append(getWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, fd));
+ worker.Append(worker.Create(OpCodes.Ret));
}
get.Body.Variables.Add(new VariableDefinition(fd.FieldType));
@@ -108,70 +130,82 @@ public static MethodDefinition ProcessSyncVarSet(TypeDefinition td, FieldDefinit
MethodAttributes.HideBySig,
Weaver.voidType);
- ILProcessor setWorker = set.Body.GetILProcessor();
+ ILProcessor worker = set.Body.GetILProcessor();
- CheckForHookFunction(td, fd, out MethodDefinition hookFunctionMethod);
+ // if (!SyncVarEqual(value, ref playerData))
+ Instruction endOfMethod = worker.Create(OpCodes.Nop);
- if (hookFunctionMethod != null)
+ // this
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ // new value to set
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ // reference to field to set
+ // make generic version of SetSyncVar with field type
+ if (fd.FieldType.FullName == Weaver.gameObjectType.FullName)
{
- //if (NetworkServer.localClientActive && !getSyncVarHookGuard(dirtyBit))
- Instruction label = setWorker.Create(OpCodes.Nop);
- setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.NetworkServerGetLocalClientActive));
- setWorker.Append(setWorker.Create(OpCodes.Brfalse, label));
- setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
- setWorker.Append(setWorker.Create(OpCodes.Ldc_I8, dirtyBit));
- setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.getSyncVarHookGuard));
- setWorker.Append(setWorker.Create(OpCodes.Brtrue, label));
-
- // setSyncVarHookGuard(dirtyBit, true);
- setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
- setWorker.Append(setWorker.Create(OpCodes.Ldc_I8, dirtyBit));
- setWorker.Append(setWorker.Create(OpCodes.Ldc_I4_1));
- setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarHookGuard));
+ // reference to netId Field to set
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
- // call hook
- setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
- setWorker.Append(setWorker.Create(OpCodes.Ldarg_1));
- setWorker.Append(setWorker.Create(OpCodes.Call, hookFunctionMethod));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.syncVarGameObjectEqualReference));
+ }
+ else if (fd.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
+ {
+ // reference to netId Field to set
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
- // setSyncVarHookGuard(dirtyBit, false);
- setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
- setWorker.Append(setWorker.Create(OpCodes.Ldc_I8, dirtyBit));
- setWorker.Append(setWorker.Create(OpCodes.Ldc_I4_0));
- setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarHookGuard));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.syncVarNetworkIdentityEqualReference));
+ }
+ else
+ {
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldflda, fd));
- setWorker.Append(label);
+ GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(Weaver.syncVarEqualReference);
+ syncVarEqualGm.GenericArguments.Add(fd.FieldType);
+ worker.Append(worker.Create(OpCodes.Call, syncVarEqualGm));
}
+ worker.Append(worker.Create(OpCodes.Brtrue, endOfMethod));
+
+ // T oldValue = value;
+ // TODO for GO/NI we need to backup the netId don't we?
+ VariableDefinition oldValue = new VariableDefinition(fd.FieldType);
+ set.Body.Variables.Add(oldValue);
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldfld, fd));
+ worker.Append(worker.Create(OpCodes.Stloc, oldValue));
+
// this
- setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
// new value to set
- setWorker.Append(setWorker.Create(OpCodes.Ldarg_1));
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
// reference to field to set
- setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
- setWorker.Append(setWorker.Create(OpCodes.Ldflda, fd));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldflda, fd));
// dirty bit
- setWorker.Append(setWorker.Create(OpCodes.Ldc_I8, dirtyBit)); // 8 byte integer aka long
-
+ // 8 byte integer aka long
+ worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
if (fd.FieldType.FullName == Weaver.gameObjectType.FullName)
{
// reference to netId Field to set
- setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
- setWorker.Append(setWorker.Create(OpCodes.Ldflda, netFieldId));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldflda, netFieldId));
- setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarGameObjectReference));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.setSyncVarGameObjectReference));
}
else if (fd.FieldType.FullName == Weaver.NetworkIdentityType.FullName)
{
// reference to netId Field to set
- setWorker.Append(setWorker.Create(OpCodes.Ldarg_0));
- setWorker.Append(setWorker.Create(OpCodes.Ldflda, netFieldId));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldflda, netFieldId));
- setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarNetworkIdentityReference));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.setSyncVarNetworkIdentityReference));
}
else
{
@@ -180,10 +214,44 @@ public static MethodDefinition ProcessSyncVarSet(TypeDefinition td, FieldDefinit
gm.GenericArguments.Add(fd.FieldType);
// invoke SetSyncVar
- setWorker.Append(setWorker.Create(OpCodes.Call, gm));
+ worker.Append(worker.Create(OpCodes.Call, gm));
+ }
+
+ MethodDefinition hookMethod = GetHookMethod(td, fd);
+
+ if (hookMethod != null)
+ {
+ //if (NetworkServer.localClientActive && !getSyncVarHookGuard(dirtyBit))
+ Instruction label = worker.Create(OpCodes.Nop);
+ worker.Append(worker.Create(OpCodes.Call, Weaver.NetworkServerGetLocalClientActive));
+ worker.Append(worker.Create(OpCodes.Brfalse, label));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.getSyncVarHookGuard));
+ worker.Append(worker.Create(OpCodes.Brtrue, label));
+
+ // setSyncVarHookGuard(dirtyBit, true);
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
+ worker.Append(worker.Create(OpCodes.Ldc_I4_1));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.setSyncVarHookGuard));
+
+ // call hook (oldValue, newValue)
+ // Generates: OnValueChanged(oldValue, value);
+ WriteCallHookMethodUsingArgument(worker, hookMethod, oldValue);
+
+ // setSyncVarHookGuard(dirtyBit, false);
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
+ worker.Append(worker.Create(OpCodes.Ldc_I4_0));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.setSyncVarHookGuard));
+
+ worker.Append(label);
}
- setWorker.Append(setWorker.Create(OpCodes.Ret));
+ worker.Append(endOfMethod);
+
+ worker.Append(worker.Create(OpCodes.Ret));
set.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.In, fd.FieldType));
set.SemanticsAttributes = MethodSemanticsAttributes.Setter;
@@ -215,7 +283,8 @@ public static void ProcessSyncVar(TypeDefinition td, FieldDefinition fd, Diction
//create the property
PropertyDefinition propertyDefinition = new PropertyDefinition("Network" + originalName, PropertyAttributes.None, fd.FieldType)
{
- GetMethod = get, SetMethod = set
+ GetMethod = get,
+ SetMethod = set
};
//add the methods and property to the type.
@@ -248,54 +317,26 @@ public static void ProcessSyncVars(TypeDefinition td, List sync
// find syncvars
foreach (FieldDefinition fd in td.Fields)
{
- foreach (CustomAttribute ca in fd.CustomAttributes)
+ if (fd.HasCustomAttribute(Weaver.SyncVarType))
{
- if (ca.AttributeType.FullName == Weaver.SyncVarType.FullName)
+ if ((fd.Attributes & FieldAttributes.Static) != 0)
{
- TypeDefinition resolvedField = fd.FieldType.Resolve();
-
- if (resolvedField.IsDerivedFrom(Weaver.NetworkBehaviourType))
- {
- Weaver.Error($"{fd} has invalid type. SyncVars cannot be NetworkBehaviours");
- return;
- }
-
- if (resolvedField.IsDerivedFrom(Weaver.ScriptableObjectType))
- {
- Weaver.Error($"{fd} has invalid type. SyncVars cannot be scriptable objects");
- return;
- }
-
- if ((fd.Attributes & FieldAttributes.Static) != 0)
- {
- Weaver.Error($"{fd} cannot be static");
- return;
- }
-
- if (resolvedField.HasGenericParameters)
- {
- Weaver.Error($"{fd} has invalid type. SyncVars cannot have generic parameters");
- return;
- }
-
- if (resolvedField.IsInterface)
- {
- Weaver.Error($"{fd} has invalid type. Use a concrete type instead of interface {fd.FieldType}");
- return;
- }
-
- if (fd.FieldType.IsArray)
- {
- Weaver.Error($"{fd} has invalid type. Use SyncLists instead of arrays");
- return;
- }
+ Weaver.Error($"{fd.Name} cannot be static", fd);
+ return;
+ }
- if (SyncObjectInitializer.ImplementsSyncObject(fd.FieldType))
- {
- Log.Warning($"{fd} has [SyncVar] attribute. SyncLists should not be marked with SyncVar");
- break;
- }
+ if (fd.FieldType.IsArray)
+ {
+ Weaver.Error($"{fd.Name} has invalid type. Use SyncLists instead of arrays", fd);
+ return;
+ }
+ if (SyncObjectInitializer.ImplementsSyncObject(fd.FieldType))
+ {
+ Weaver.Warning($"{fd.Name} has [SyncVar] attribute. SyncLists should not be marked with SyncVar", fd);
+ }
+ else
+ {
syncVars.Add(fd);
ProcessSyncVar(td, fd, syncVarNetIds, 1L << dirtyBitCounter);
@@ -304,10 +345,9 @@ public static void ProcessSyncVars(TypeDefinition td, List sync
if (dirtyBitCounter == SyncVarLimit)
{
- Weaver.Error($"{td} has too many SyncVars. Consider refactoring your class into multiple components");
+ Weaver.Error($"{td.Name} has too many SyncVars. Consider refactoring your class into multiple components", td);
return;
}
- break;
}
}
@@ -315,7 +355,13 @@ public static void ProcessSyncVars(TypeDefinition td, List sync
{
if (fd.IsStatic)
{
- Weaver.Error($"{fd} cannot be static");
+ Weaver.Error($"{fd.Name} cannot be static", fd);
+ return;
+ }
+
+ if (fd.FieldType.Resolve().HasGenericParameters)
+ {
+ Weaver.Error($"Cannot use generic SyncObject {fd.Name} directly in NetworkBehaviour. Create a class and inherit from the generic SyncObject instead", fd);
return;
}
@@ -331,5 +377,76 @@ public static void ProcessSyncVars(TypeDefinition td, List sync
Weaver.SetNumSyncVars(td.FullName, numSyncVars);
}
+
+ public static void WriteCallHookMethodUsingArgument(ILProcessor worker, MethodDefinition hookMethod, VariableDefinition oldValue)
+ {
+ _WriteCallHookMethod(worker, hookMethod, oldValue, null);
+ }
+
+ public static void WriteCallHookMethodUsingField(ILProcessor worker, MethodDefinition hookMethod, VariableDefinition oldValue, FieldDefinition newValue)
+ {
+ if (newValue == null)
+ {
+ Weaver.Error("NewValue field was null when writing SyncVar hook");
+ }
+
+ _WriteCallHookMethod(worker, hookMethod, oldValue, newValue);
+ }
+
+ static void _WriteCallHookMethod(ILProcessor worker, MethodDefinition hookMethod, VariableDefinition oldValue, FieldDefinition newValue)
+ {
+ WriteStartFunctionCall();
+
+ // write args
+ WriteOldValue();
+ WriteNewValue();
+
+ WriteEndFunctionCall();
+
+
+ // *** Local functions used to write OpCodes ***
+ // Local functions have access to function variables, no need to pass in args
+
+ void WriteOldValue()
+ {
+ worker.Append(worker.Create(OpCodes.Ldloc, oldValue));
+ }
+
+ void WriteNewValue()
+ {
+ // write arg1 or this.field
+ if (newValue == null)
+ {
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
+ }
+ else
+ {
+ // this.
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ // syncvar.get
+ worker.Append(worker.Create(OpCodes.Ldfld, newValue));
+ }
+ }
+
+ // Writes this before method if it is not static
+ void WriteStartFunctionCall()
+ {
+ // dont add this (Ldarg_0) if method is static
+ if (!hookMethod.IsStatic)
+ {
+ // this before method call
+ // eg this.onValueChanged
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ }
+ }
+
+ // Calls method
+ void WriteEndFunctionCall()
+ {
+ // only use Callvirt when not static
+ OpCode opcode = hookMethod.IsStatic ? OpCodes.Call : OpCodes.Callvirt;
+ worker.Append(worker.Create(opcode, hookMethod));
+ }
+ }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs
index 3676e21..bd0494a 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs
@@ -1,13 +1,13 @@
-// all the [TargetRpc] code from NetworkBehaviourProcessor in one place
using Mono.CecilX;
using Mono.CecilX.Cil;
namespace Mirror.Weaver
{
+ ///
+ /// Processes [TargetRpc] methods in NetworkBehaviour
+ ///
public static class TargetRpcProcessor
{
- const string TargetRpcPrefix = "InvokeTargetRpc";
-
// helper functions to check if the method has a NetworkConnection parameter
public static bool HasNetworkConnectionParameter(MethodDefinition md)
{
@@ -17,38 +17,38 @@ public static bool HasNetworkConnectionParameter(MethodDefinition md)
public static MethodDefinition ProcessTargetRpcInvoke(TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc)
{
- MethodDefinition rpc = new MethodDefinition(RpcProcessor.RpcPrefix + md.Name, MethodAttributes.Family |
+ MethodDefinition rpc = new MethodDefinition(Weaver.InvokeRpcPrefix + md.Name, MethodAttributes.Family |
MethodAttributes.Static |
MethodAttributes.HideBySig,
Weaver.voidType);
- ILProcessor rpcWorker = rpc.Body.GetILProcessor();
- Instruction label = rpcWorker.Create(OpCodes.Nop);
+ ILProcessor worker = rpc.Body.GetILProcessor();
+ Instruction label = worker.Create(OpCodes.Nop);
- NetworkBehaviourProcessor.WriteClientActiveCheck(rpcWorker, md.Name, label, "TargetRPC");
+ NetworkBehaviourProcessor.WriteClientActiveCheck(worker, md.Name, label, "TargetRPC");
// setup for reader
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0));
- rpcWorker.Append(rpcWorker.Create(OpCodes.Castclass, td));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Castclass, td));
// NetworkConnection parameter is optional
- bool hasNetworkConnection = HasNetworkConnectionParameter(md);
- if (hasNetworkConnection)
+ if (HasNetworkConnectionParameter(md))
{
+ // if call has NetworkConnection write clients connection as first arg
//ClientScene.readyconnection
- rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.ReadyConnectionReference));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.ReadyConnectionReference));
}
// process reader parameters and skip first one if first one is NetworkConnection
- if (!NetworkBehaviourProcessor.ProcessNetworkReaderParameters(md, rpcWorker, hasNetworkConnection))
+ if (!NetworkBehaviourProcessor.ReadArguments(md, worker, RemoteCallType.TargetRpc))
return null;
// invoke actual command function
- rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, rpcCallFunc));
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Callvirt, rpcCallFunc));
+ worker.Append(worker.Create(OpCodes.Ret));
NetworkBehaviourProcessor.AddInvokeParameters(rpc.Parameters);
-
+ td.Methods.Add(rpc);
return rpc;
}
@@ -79,85 +79,63 @@ public void CallTargetTest (int param)
Originally HLAPI put the send message code inside the Call function
and then proceeded to replace every call to TargetTest with CallTargetTest
- This method moves all the user's code into the "Call" method
+ This method moves all the user's code into the "CallTargetRpc" method
and replaces the body of the original method with the send message code.
This way we do not need to modify the code anywhere else, and this works
correctly in dependent assemblies
-
+
*/
- public static MethodDefinition ProcessTargetRpcCall(TypeDefinition td, MethodDefinition md, CustomAttribute ca)
+ public static MethodDefinition ProcessTargetRpcCall(TypeDefinition td, MethodDefinition md, CustomAttribute targetRpcAttr)
{
- MethodDefinition rpc = new MethodDefinition("Call" + md.Name, MethodAttributes.Public |
- MethodAttributes.HideBySig,
- Weaver.voidType);
-
- // add parameters
- foreach (ParameterDefinition pd in md.Parameters)
- {
- rpc.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType));
- }
+ MethodDefinition rpc = MethodProcessor.SubstituteMethod(td, md);
- // move the old body to the new function
- MethodBody newBody = rpc.Body;
- rpc.Body = md.Body;
- md.Body = newBody;
+ ILProcessor worker = md.Body.GetILProcessor();
- ILProcessor rpcWorker = md.Body.GetILProcessor();
+ NetworkBehaviourProcessor.WriteSetupLocals(worker);
- NetworkBehaviourProcessor.WriteSetupLocals(rpcWorker);
-
- NetworkBehaviourProcessor.WriteCreateWriter(rpcWorker);
-
- // NetworkConnection parameter is optional
- bool hasNetworkConnection = HasNetworkConnectionParameter(md);
+ NetworkBehaviourProcessor.WriteCreateWriter(worker);
// write all the arguments that the user passed to the TargetRpc call
// (skip first one if first one is NetworkConnection)
- if (!NetworkBehaviourProcessor.WriteArguments(rpcWorker, md, hasNetworkConnection))
+ if (!NetworkBehaviourProcessor.WriteArguments(worker, md, RemoteCallType.TargetRpc))
return null;
string rpcName = md.Name;
- int index = rpcName.IndexOf(TargetRpcPrefix);
- if (index > -1)
- {
- rpcName = rpcName.Substring(TargetRpcPrefix.Length);
- }
// invoke SendInternal and return
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); // this
+ // this
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
if (HasNetworkConnectionParameter(md))
{
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_1)); // connection
+ // connection
+ worker.Append(worker.Create(OpCodes.Ldarg_1));
}
else
{
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldnull)); // null
+ // null
+ worker.Append(worker.Create(OpCodes.Ldnull));
}
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldtoken, td));
- rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); // invokerClass
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName));
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0)); // writer
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, NetworkBehaviourProcessor.GetChannelId(ca)));
- rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendTargetRpcInternal));
+ worker.Append(worker.Create(OpCodes.Ldtoken, td));
+ // invokerClass
+ worker.Append(worker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference));
+ worker.Append(worker.Create(OpCodes.Ldstr, rpcName));
+ // writer
+ worker.Append(worker.Create(OpCodes.Ldloc_0));
+ worker.Append(worker.Create(OpCodes.Ldc_I4, targetRpcAttr.GetField("channel", 0)));
+ worker.Append(worker.Create(OpCodes.Callvirt, Weaver.sendTargetRpcInternal));
- NetworkBehaviourProcessor.WriteRecycleWriter(rpcWorker);
+ NetworkBehaviourProcessor.WriteRecycleWriter(worker);
- rpcWorker.Append(rpcWorker.Create(OpCodes.Ret));
+ worker.Append(worker.Create(OpCodes.Ret));
return rpc;
}
- public static bool ProcessMethodsValidateTargetRpc(MethodDefinition md, CustomAttribute ca)
+ public static bool ProcessMethodsValidateTargetRpc(MethodDefinition md)
{
- if (!md.Name.StartsWith("Target"))
- {
- Weaver.Error($"{md} must start with Target. Consider renaming it to Target{md.Name}");
- return false;
- }
-
if (md.IsStatic)
{
- Weaver.Error($"{md} must not be static");
+ Weaver.Error($"{md.Name} must not be static", md);
return false;
}
@@ -167,7 +145,7 @@ public static bool ProcessMethodsValidateTargetRpc(MethodDefinition md, CustomAt
}
// validate
- return NetworkBehaviourProcessor.ProcessMethodsValidateParameters(md, ca);
+ return NetworkBehaviourProcessor.ProcessMethodsValidateParameters(md, RemoteCallType.TargetRpc);
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Program.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Program.cs
index 62163d2..e3e9bd3 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Program.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Program.cs
@@ -11,12 +11,12 @@ public static class Log
public static void Warning(string msg)
{
- WarningMethod("Mirror.Weaver warning: " + msg);
+ WarningMethod(msg);
}
public static void Error(string msg)
{
- ErrorMethod("Mirror.Weaver error: " + msg);
+ ErrorMethod(msg);
}
}
@@ -24,8 +24,8 @@ public static class Program
{
public static bool Process(string unityEngine, string netDLL, string outputDirectory, string[] assemblies, string[] extraAssemblyPaths, Action printWarning, Action printError)
{
- CheckDLLPath(unityEngine);
- CheckDLLPath(netDLL);
+ CheckDllPath(unityEngine);
+ CheckDllPath(netDLL);
CheckOutputDirectory(outputDirectory);
CheckAssemblies(assemblies);
Log.WarningMethod = printWarning;
@@ -33,7 +33,7 @@ public static bool Process(string unityEngine, string netDLL, string outputDirec
return Weaver.WeaveAssemblies(assemblies, extraAssemblyPaths, outputDirectory, unityEngine, netDLL);
}
- static void CheckDLLPath(string path)
+ static void CheckDllPath(string path)
{
if (!File.Exists(path))
throw new Exception("dll could not be located at " + path + "!");
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Readers.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Readers.cs
index a50798d..11b977b 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Readers.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Readers.cs
@@ -3,7 +3,6 @@
using Mono.CecilX.Cil;
using Mono.CecilX.Rocks;
-
namespace Mirror.Weaver
{
public static class Readers
@@ -28,27 +27,58 @@ public static MethodReference GetReadFunc(TypeReference variable, int recursionC
return foundFunc;
}
+ MethodDefinition newReaderFunc;
+
+ // Arrays are special, if we resolve them, we get teh element type,
+ // so the following ifs might choke on it for scriptable objects
+ // or other objects that require a custom serializer
+ // thus check if it is an array and skip all the checks.
+ if (variable.IsArray)
+ {
+ newReaderFunc = GenerateArrayReadFunc(variable, recursionCount);
+ RegisterReadFunc(variable.FullName, newReaderFunc);
+ return newReaderFunc;
+ }
+
TypeDefinition td = variable.Resolve();
if (td == null)
{
- Weaver.Error($"{variable} is not a supported type");
+ Weaver.Error($"{variable.Name} is not a supported type", variable);
+ return null;
+ }
+ if (td.IsDerivedFrom(Weaver.ComponentType))
+ {
+ Weaver.Error($"Cannot generate reader for component type {variable.Name}. Use a supported type or provide a custom reader", variable);
+ return null;
+ }
+ if (variable.FullName == Weaver.ObjectType.FullName)
+ {
+ Weaver.Error($"Cannot generate reader for {variable.Name}. Use a supported type or provide a custom reader", variable);
+ return null;
+ }
+ if (variable.FullName == Weaver.ScriptableObjectType.FullName)
+ {
+ Weaver.Error($"Cannot generate reader for {variable.Name}. Use a supported type or provide a custom reader", variable);
return null;
}
-
if (variable.IsByReference)
{
// error??
- Weaver.Error($"{variable} is not a supported reference type");
+ Weaver.Error($"Cannot pass type {variable.Name} by reference", variable);
return null;
}
-
- MethodDefinition newReaderFunc;
-
- if (variable.IsArray)
+ if (td.HasGenericParameters && !td.FullName.StartsWith("System.ArraySegment`1", System.StringComparison.Ordinal))
{
- newReaderFunc = GenerateArrayReadFunc(variable, recursionCount);
+ Weaver.Error($"Cannot generate reader for generic variable {variable.Name}. Use a supported type or provide a custom reader", variable);
+ return null;
}
- else if (td.IsEnum)
+ if (td.IsInterface)
+ {
+ Weaver.Error($"Cannot generate reader for interface {variable.Name}. Use a supported type or provide a custom reader", variable);
+ return null;
+ }
+
+ if (td.IsEnum)
{
return GetReadFunc(td.GetEnumUnderlyingType(), recursionCount);
}
@@ -58,12 +88,12 @@ public static MethodReference GetReadFunc(TypeReference variable, int recursionC
}
else
{
- newReaderFunc = GenerateStructReadFunction(variable, recursionCount);
+ newReaderFunc = GenerateClassOrStructReadFunction(variable, recursionCount);
}
if (newReaderFunc == null)
{
- Weaver.Error($"{variable} is not a supported type");
+ Weaver.Error($"{variable.Name} is not a supported type", variable);
return null;
}
RegisterReadFunc(variable.FullName, newReaderFunc);
@@ -83,7 +113,7 @@ static MethodDefinition GenerateArrayReadFunc(TypeReference variable, int recurs
{
if (!variable.IsArrayType())
{
- Weaver.Error($"{variable} is an unsupported type. Jagged and multidimensional arrays are not supported");
+ Weaver.Error($"{variable.Name} is an unsupported type. Jagged and multidimensional arrays are not supported", variable);
return null;
}
@@ -137,13 +167,11 @@ static MethodDefinition GenerateArrayReadFunc(TypeReference variable, int recurs
worker.Append(worker.Create(OpCodes.Ret));
worker.Append(labelEmptyArray);
-
// T value = new T[length];
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Newarr, variable.GetElementType()));
worker.Append(worker.Create(OpCodes.Stloc_1));
-
// for (int i=0; i< length ; i++) {
worker.Append(worker.Create(OpCodes.Ldc_I4_0));
worker.Append(worker.Create(OpCodes.Stloc_2));
@@ -161,7 +189,6 @@ static MethodDefinition GenerateArrayReadFunc(TypeReference variable, int recurs
worker.Append(worker.Create(OpCodes.Call, elementReadFunc));
worker.Append(worker.Create(OpCodes.Stobj, variable.GetElementType()));
-
worker.Append(worker.Create(OpCodes.Ldloc_2));
worker.Append(worker.Create(OpCodes.Ldc_I4_1));
worker.Append(worker.Create(OpCodes.Add));
@@ -218,21 +245,20 @@ static MethodDefinition GenerateArraySegmentReadFunc(TypeReference variable, int
readerFunc.Body.InitLocals = true;
ILProcessor worker = readerFunc.Body.GetILProcessor();
-
+
// int length = reader.ReadPackedInt32();
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Call, GetReadFunc(Weaver.int32Type)));
worker.Append(worker.Create(OpCodes.Stloc_0));
-
+
// T[] array = new int[length]
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Newarr, elementType));
worker.Append(worker.Create(OpCodes.Stloc_1));
-
// loop through array and deserialize each element
// generates code like this
- // for (int i=0; i< length ; i++)
+ // for (int i=0; i< length ; i++)
// {
// value[i] = reader.ReadXXX();
// }
@@ -244,15 +270,13 @@ static MethodDefinition GenerateArraySegmentReadFunc(TypeReference variable, int
// loop body
Instruction labelBody = worker.Create(OpCodes.Nop);
worker.Append(labelBody);
- {
- // value[i] = reader.ReadT();
- worker.Append(worker.Create(OpCodes.Ldloc_1));
- worker.Append(worker.Create(OpCodes.Ldloc_2));
- worker.Append(worker.Create(OpCodes.Ldelema, elementType));
- worker.Append(worker.Create(OpCodes.Ldarg_0));
- worker.Append(worker.Create(OpCodes.Call, elementReadFunc));
- worker.Append(worker.Create(OpCodes.Stobj, elementType));
- }
+ // value[i] = reader.ReadT();
+ worker.Append(worker.Create(OpCodes.Ldloc_1));
+ worker.Append(worker.Create(OpCodes.Ldloc_2));
+ worker.Append(worker.Create(OpCodes.Ldelema, elementType));
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Call, elementReadFunc));
+ worker.Append(worker.Create(OpCodes.Stobj, elementType));
worker.Append(worker.Create(OpCodes.Ldloc_2));
worker.Append(worker.Create(OpCodes.Ldc_I4_1));
@@ -264,7 +288,7 @@ static MethodDefinition GenerateArraySegmentReadFunc(TypeReference variable, int
worker.Append(worker.Create(OpCodes.Ldloc_2));
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Blt, labelBody));
-
+
// return new ArraySegment(array);
worker.Append(worker.Create(OpCodes.Ldloc_1));
worker.Append(worker.Create(OpCodes.Newobj, Weaver.ArraySegmentConstructorReference.MakeHostInstanceGeneric(genericInstance)));
@@ -272,16 +296,11 @@ static MethodDefinition GenerateArraySegmentReadFunc(TypeReference variable, int
return readerFunc;
}
- static MethodDefinition GenerateStructReadFunction(TypeReference variable, int recursionCount)
+ static MethodDefinition GenerateClassOrStructReadFunction(TypeReference variable, int recursionCount)
{
if (recursionCount > MaxRecursionCount)
{
- Weaver.Error($"{variable} can't be deserialized because it references itself");
- return null;
- }
-
- if (!Weaver.IsValidTypeToGenerate(variable.Resolve()))
- {
+ Weaver.Error($"{variable.Name} can't be deserialized because it references itself", variable);
return null;
}
@@ -310,12 +329,32 @@ static MethodDefinition GenerateStructReadFunction(TypeReference variable, int r
ILProcessor worker = readerFunc.Body.GetILProcessor();
+ TypeDefinition td = variable.Resolve();
+
+ CreateNew(variable, worker, td);
+ ReadAllFields(variable, recursionCount, worker);
+
+ worker.Append(worker.Create(OpCodes.Ldloc_0));
+ worker.Append(worker.Create(OpCodes.Ret));
+ return readerFunc;
+ }
+
+ // Initialize the local variable with a new instance
+ static void CreateNew(TypeReference variable, ILProcessor worker, TypeDefinition td)
+ {
if (variable.IsValueType)
{
// structs are created with Initobj
worker.Append(worker.Create(OpCodes.Ldloca, 0));
worker.Append(worker.Create(OpCodes.Initobj, variable));
}
+ else if (td.IsDerivedFrom(Weaver.ScriptableObjectType))
+ {
+ GenericInstanceMethod genericInstanceMethod = new GenericInstanceMethod(Weaver.ScriptableObjectCreateInstanceMethod);
+ genericInstanceMethod.GenericArguments.Add(variable);
+ worker.Append(worker.Create(OpCodes.Call, genericInstanceMethod));
+ worker.Append(worker.Create(OpCodes.Stloc_0));
+ }
else
{
// classes are created with their constructor
@@ -323,20 +362,22 @@ static MethodDefinition GenerateStructReadFunction(TypeReference variable, int r
MethodDefinition ctor = Resolvers.ResolveDefaultPublicCtor(variable);
if (ctor == null)
{
- Weaver.Error($"{variable} can't be deserialized bcause i has no default constructor");
- return null;
+ Weaver.Error($"{variable.Name} can't be deserialized because it has no default constructor", variable);
+ return;
}
- worker.Append(worker.Create(OpCodes.Newobj, ctor));
+ MethodReference ctorRef = Weaver.CurrentAssembly.MainModule.ImportReference(ctor);
+
+ worker.Append(worker.Create(OpCodes.Newobj, ctorRef));
worker.Append(worker.Create(OpCodes.Stloc_0));
}
+ }
+ static void ReadAllFields(TypeReference variable, int recursionCount, ILProcessor worker)
+ {
uint fields = 0;
- foreach (FieldDefinition field in variable.Resolve().Fields)
+ foreach (FieldDefinition field in variable.FindAllPublicFields())
{
- if (field.IsStatic || field.IsPrivate)
- continue;
-
// mismatched ldloca/ldloc for struct/class combinations is invalid IL, which causes crash at runtime
OpCode opcode = variable.IsValueType ? OpCodes.Ldloca : OpCodes.Ldloc;
worker.Append(worker.Create(opcode, 0));
@@ -349,21 +390,18 @@ static MethodDefinition GenerateStructReadFunction(TypeReference variable, int r
}
else
{
- Weaver.Error($"{field} has an unsupported type");
- return null;
+ Weaver.Error($"{field.Name} has an unsupported type", field);
}
+ FieldReference fieldRef = Weaver.CurrentAssembly.MainModule.ImportReference(field);
- worker.Append(worker.Create(OpCodes.Stfld, field));
+ worker.Append(worker.Create(OpCodes.Stfld, fieldRef));
fields++;
}
+
if (fields == 0)
{
Log.Warning($"{variable} has no public or non-static fields to deserialize");
}
-
- worker.Append(worker.Create(OpCodes.Ldloc_0));
- worker.Append(worker.Create(OpCodes.Ret));
- return readerFunc;
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Resolvers.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Resolvers.cs
index 434aed4..3d868eb 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Resolvers.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Resolvers.cs
@@ -12,29 +12,37 @@ public static class Resolvers
{
public static MethodReference ResolveMethod(TypeReference tr, AssemblyDefinition scriptDef, string name)
{
- //Console.WriteLine("ResolveMethod " + t.ToString () + " " + name);
if (tr == null)
{
- Weaver.Error("Type missing for " + name);
+ Weaver.Error($"Cannot resolve method {name} without a class");
return null;
}
- foreach (MethodDefinition methodRef in tr.Resolve().Methods)
+ MethodReference method = ResolveMethod(tr, scriptDef, m => m.Name == name);
+ if (method == null)
{
- if (methodRef.Name == name)
+ Weaver.Error($"Method not found with name {name} in type {tr.Name}", tr);
+ }
+ return method;
+ }
+
+ public static MethodReference ResolveMethod(TypeReference t, AssemblyDefinition scriptDef, System.Func predicate)
+ {
+ foreach (MethodDefinition methodRef in t.Resolve().Methods)
+ {
+ if (predicate(methodRef))
{
return scriptDef.MainModule.ImportReference(methodRef);
}
}
- Weaver.Error($"{tr}.{name}() not found");
+
+ Weaver.Error($"Method not found in type {t.Name}", t);
return null;
}
- // TODO reuse ResolveMethod in here after Weaver.fail was removed
- public static MethodReference ResolveMethodInParents(TypeReference tr, AssemblyDefinition scriptDef, string name)
+ public static MethodReference TryResolveMethodInParents(TypeReference tr, AssemblyDefinition scriptDef, string name)
{
if (tr == null)
{
- Weaver.Error("Type missing for " + name);
return null;
}
foreach (MethodDefinition methodRef in tr.Resolve().Methods)
@@ -44,28 +52,20 @@ public static MethodReference ResolveMethodInParents(TypeReference tr, AssemblyD
return scriptDef.MainModule.ImportReference(methodRef);
}
}
+
// Could not find the method in this class, try the parent
- return ResolveMethodInParents(tr.Resolve().BaseType, scriptDef, name);
+ return TryResolveMethodInParents(tr.Resolve().BaseType, scriptDef, name);
}
// System.Byte[] arguments need a version with a string
public static MethodReference ResolveMethodWithArg(TypeReference tr, AssemblyDefinition scriptDef, string name, string argTypeFullName)
{
- foreach (MethodDefinition methodRef in tr.Resolve().Methods)
- {
- if (methodRef.Name == name)
- {
- if (methodRef.Parameters.Count == 1)
- {
- if (methodRef.Parameters[0].ParameterType.FullName == argTypeFullName)
- {
- return scriptDef.MainModule.ImportReference(methodRef);
- }
- }
- }
- }
- Weaver.Error($"{tr}.{name}({argTypeFullName}) not found");
- return null;
+ bool match(MethodDefinition method) =>
+ method.Name == name
+ && (method.Parameters.Count == 1)
+ && method.Parameters[0].ParameterType.FullName == argTypeFullName;
+
+ return ResolveMethod(tr, scriptDef, match);
}
// reuse ResolveMethodWithArg string version
@@ -92,37 +92,19 @@ public static GenericInstanceMethod ResolveMethodGeneric(TypeReference t, Assemb
{
foreach (MethodDefinition methodRef in t.Resolve().Methods)
{
- if (methodRef.Name == name)
+ if (methodRef.Name == name && methodRef.Parameters.Count == 0 && methodRef.GenericParameters.Count == 1)
{
- if (methodRef.Parameters.Count == 0)
+ MethodReference tmp = scriptDef.MainModule.ImportReference(methodRef);
+ GenericInstanceMethod gm = new GenericInstanceMethod(tmp);
+ gm.GenericArguments.Add(genericType);
+ if (gm.GenericArguments[0].FullName == genericType.FullName)
{
- if (methodRef.GenericParameters.Count == 1)
- {
- MethodReference tmp = scriptDef.MainModule.ImportReference(methodRef);
- GenericInstanceMethod gm = new GenericInstanceMethod(tmp);
- gm.GenericArguments.Add(genericType);
- if (gm.GenericArguments[0].FullName == genericType.FullName)
- {
- return gm;
- }
- }
+ return gm;
}
}
}
- Weaver.Error($"{t}.{name}<{genericType}>() not found");
- return null;
- }
-
- public static FieldReference ResolveField(TypeReference tr, AssemblyDefinition scriptDef, string name)
- {
- foreach (FieldDefinition fd in tr.Resolve().Fields)
- {
- if (fd.Name == name)
- {
- return scriptDef.MainModule.ImportReference(fd);
- }
- }
+ Weaver.Error($"Method {name} not found in {t.Name}", t);
return null;
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Weaver.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Weaver.cs
index 3ccef36..8fb3e99 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Weaver.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Weaver.cs
@@ -27,8 +27,11 @@ class WeaverLists
public Dictionary numSyncVars = new Dictionary();
}
- class Weaver
+ internal static class Weaver
{
+ public static string InvokeRpcPrefix => "InvokeUserCode_";
+ public static string SyncEventPrefix => "SendEventMessage_";
+
public static WeaverLists WeaveLists { get; private set; }
public static AssemblyDefinition CurrentAssembly { get; private set; }
public static ModuleDefinition CorLibModule { get; private set; }
@@ -42,16 +45,19 @@ class Weaver
// Network types
public static TypeReference NetworkBehaviourType;
- public static TypeReference NetworkBehaviourType2;
+ public static TypeReference RemoteCallHelperType;
public static TypeReference MonoBehaviourType;
public static TypeReference ScriptableObjectType;
public static TypeReference NetworkConnectionType;
public static TypeReference MessageBaseType;
+ public static TypeReference IMessageBaseType;
public static TypeReference SyncListType;
public static TypeReference SyncSetType;
public static TypeReference SyncDictionaryType;
+ public static MethodReference ScriptableObjectCreateInstanceMethod;
+
public static MethodReference NetworkBehaviourDirtyBitsReference;
public static MethodReference GetPooledWriterReference;
public static MethodReference RecycleWriterReference;
@@ -61,6 +67,7 @@ class Weaver
public static TypeReference NetworkReaderType;
public static TypeReference NetworkWriterType;
+ public static TypeReference PooledNetworkWriterType;
public static TypeReference NetworkIdentityType;
public static TypeReference IEnumeratorType;
@@ -69,6 +76,7 @@ class Weaver
public static MethodReference ReadyConnectionReference;
public static TypeReference ComponentType;
+ public static TypeReference ObjectType;
public static TypeReference CmdDelegateReference;
public static MethodReference CmdDelegateConstructor;
@@ -76,7 +84,6 @@ class Weaver
public static MethodReference NetworkServerGetActive;
public static MethodReference NetworkServerGetLocalClientActive;
public static MethodReference NetworkClientGetActive;
- public static MethodReference getBehaviourIsServer;
// custom attribute types
public static TypeReference SyncVarType;
@@ -108,6 +115,9 @@ class Weaver
public static TypeReference gameObjectType;
public static TypeReference transformType;
+ public static MethodReference syncVarEqualReference;
+ public static MethodReference syncVarNetworkIdentityEqualReference;
+ public static MethodReference syncVarGameObjectEqualReference;
public static MethodReference setSyncVarReference;
public static MethodReference setSyncVarHookGuard;
public static MethodReference getSyncVarHookGuard;
@@ -143,6 +153,17 @@ public static void Error(string message)
WeavingFailed = true;
}
+ public static void Error(string message, MemberReference mr)
+ {
+ Log.Error($"{message} (at {mr})");
+ WeavingFailed = true;
+ }
+
+ public static void Warning(string message, MemberReference mr)
+ {
+ Log.Warning($"{message} (at {mr})");
+ }
+
public static int GetSyncVarStart(string className)
{
return WeaveLists.numSyncVars.ContainsKey(className)
@@ -245,16 +266,18 @@ static void SetupTargetTypes()
ArraySegmentOffsetReference = Resolvers.ResolveProperty(ArraySegmentType, CurrentAssembly, "Offset");
ArraySegmentConstructorReference = Resolvers.ResolveMethod(ArraySegmentType, CurrentAssembly, ".ctor");
-
NetworkReaderType = NetAssembly.MainModule.GetType("Mirror.NetworkReader");
NetworkWriterType = NetAssembly.MainModule.GetType("Mirror.NetworkWriter");
+ TypeReference pooledNetworkWriterTmp = NetAssembly.MainModule.GetType("Mirror.PooledNetworkWriter");
+ PooledNetworkWriterType = CurrentAssembly.MainModule.ImportReference(pooledNetworkWriterTmp);
NetworkServerGetActive = Resolvers.ResolveMethod(NetworkServerType, CurrentAssembly, "get_active");
NetworkServerGetLocalClientActive = Resolvers.ResolveMethod(NetworkServerType, CurrentAssembly, "get_localClientActive");
NetworkClientGetActive = Resolvers.ResolveMethod(NetworkClientType, CurrentAssembly, "get_active");
- CmdDelegateReference = NetAssembly.MainModule.GetType("Mirror.NetworkBehaviour/CmdDelegate");
+ CmdDelegateReference = NetAssembly.MainModule.GetType("Mirror.RemoteCalls.CmdDelegate");
CmdDelegateConstructor = Resolvers.ResolveMethod(CmdDelegateReference, CurrentAssembly, ".ctor");
+
CurrentAssembly.MainModule.ImportReference(gameObjectType);
CurrentAssembly.MainModule.ImportReference(transformType);
@@ -262,16 +285,21 @@ static void SetupTargetTypes()
NetworkIdentityType = CurrentAssembly.MainModule.ImportReference(networkIdentityTmp);
NetworkBehaviourType = NetAssembly.MainModule.GetType("Mirror.NetworkBehaviour");
- NetworkBehaviourType2 = CurrentAssembly.MainModule.ImportReference(NetworkBehaviourType);
+ RemoteCallHelperType = NetAssembly.MainModule.GetType("Mirror.RemoteCalls.RemoteCallHelper");
NetworkConnectionType = NetAssembly.MainModule.GetType("Mirror.NetworkConnection");
MonoBehaviourType = UnityAssembly.MainModule.GetType("UnityEngine.MonoBehaviour");
ScriptableObjectType = UnityAssembly.MainModule.GetType("UnityEngine.ScriptableObject");
+ ScriptableObjectCreateInstanceMethod = Resolvers.ResolveMethod(
+ ScriptableObjectType, CurrentAssembly,
+ md => md.Name == "CreateInstance" && md.HasGenericParameters);
+
NetworkConnectionType = NetAssembly.MainModule.GetType("Mirror.NetworkConnection");
NetworkConnectionType = CurrentAssembly.MainModule.ImportReference(NetworkConnectionType);
MessageBaseType = NetAssembly.MainModule.GetType("Mirror.MessageBase");
+ IMessageBaseType = NetAssembly.MainModule.GetType("Mirror.IMessageBase");
SyncListType = NetAssembly.MainModule.GetType("Mirror.SyncList`1");
SyncSetType = NetAssembly.MainModule.GetType("Mirror.SyncSet`1");
SyncDictionaryType = NetAssembly.MainModule.GetType("Mirror.SyncDictionary`2");
@@ -282,10 +310,13 @@ static void SetupTargetTypes()
RecycleWriterReference = Resolvers.ResolveMethod(NetworkWriterPoolType, CurrentAssembly, "Recycle");
ComponentType = UnityAssembly.MainModule.GetType("UnityEngine.Component");
+ ObjectType = UnityAssembly.MainModule.GetType("UnityEngine.Object");
ClientSceneType = NetAssembly.MainModule.GetType("Mirror.ClientScene");
ReadyConnectionReference = Resolvers.ResolveMethod(ClientSceneType, CurrentAssembly, "get_readyConnection");
- getBehaviourIsServer = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "get_isServer");
+ syncVarEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SyncVarEqual");
+ syncVarNetworkIdentityEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SyncVarNetworkIdentityEqual");
+ syncVarGameObjectEqualReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SyncVarGameObjectEqual");
setSyncVarReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SetSyncVar");
setSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "setSyncVarHookGuard");
getSyncVarHookGuard = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "getSyncVarHookGuard");
@@ -294,9 +325,9 @@ static void SetupTargetTypes()
getSyncVarGameObjectReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "GetSyncVarGameObject");
setSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "SetSyncVarNetworkIdentity");
getSyncVarNetworkIdentityReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "GetSyncVarNetworkIdentity");
- registerCommandDelegateReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "RegisterCommandDelegate");
- registerRpcDelegateReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "RegisterRpcDelegate");
- registerEventDelegateReference = Resolvers.ResolveMethod(NetworkBehaviourType, CurrentAssembly, "RegisterEventDelegate");
+ registerCommandDelegateReference = Resolvers.ResolveMethod(RemoteCallHelperType, CurrentAssembly, "RegisterCommandDelegate");
+ registerRpcDelegateReference = Resolvers.ResolveMethod(RemoteCallHelperType, CurrentAssembly, "RegisterRpcDelegate");
+ registerEventDelegateReference = Resolvers.ResolveMethod(RemoteCallHelperType, CurrentAssembly, "RegisterEventDelegate");
getTypeReference = Resolvers.ResolveMethod(objectType, CurrentAssembly, "GetType");
getTypeFromHandleReference = Resolvers.ResolveMethod(typeType, CurrentAssembly, "GetTypeFromHandle");
logErrorReference = Resolvers.ResolveMethod(UnityAssembly.MainModule.GetType("UnityEngine.Debug"), CurrentAssembly, "LogError");
@@ -315,15 +346,6 @@ public static bool IsNetworkBehaviour(TypeDefinition td)
return td.IsDerivedFrom(NetworkBehaviourType);
}
- public static bool IsValidTypeToGenerate(TypeDefinition variable)
- {
- // a valid type is a simple class or struct. so we generate only code for types we dont know, and if they are not inside
- // this assembly it must mean that we are trying to serialize a variable outside our scope. and this will fail.
- // no need to report an error here, the caller will report a better error
- string assembly = CurrentAssembly.MainModule.Name;
- return variable.Module.Name == assembly;
- }
-
static void CheckMonoBehaviour(TypeDefinition td)
{
if (td.IsDerivedFrom(MonoBehaviourType))
@@ -332,7 +354,7 @@ static void CheckMonoBehaviour(TypeDefinition td)
}
}
- static bool CheckNetworkBehaviour(TypeDefinition td)
+ static bool WeaveNetworkBehavior(TypeDefinition td)
{
if (!td.IsClass)
return false;
@@ -367,100 +389,93 @@ static bool CheckNetworkBehaviour(TypeDefinition td)
}
}
- bool didWork = false;
+ bool modified = false;
foreach (TypeDefinition behaviour in behaviourClasses)
{
- didWork |= ProcessNetworkBehaviourType(behaviour);
+ modified |= ProcessNetworkBehaviourType(behaviour);
}
- return didWork;
+ return modified;
}
- static bool CheckMessageBase(TypeDefinition td)
+ static bool WeaveMessage(TypeDefinition td)
{
if (!td.IsClass)
return false;
- bool didWork = false;
+ bool modified = false;
- // are ANY parent classes MessageBase
- TypeReference parent = td.BaseType;
- while (parent != null)
+ if (td.ImplementsInterface(IMessageBaseType))
{
- if (parent.FullName == MessageBaseType.FullName)
- {
- MessageClassProcessor.Process(td);
- didWork = true;
- break;
- }
+ // process this and base classes from parent to child order
+
try
{
- parent = parent.Resolve().BaseType;
+ TypeDefinition parent = td.BaseType.Resolve();
+ // process parent
+ WeaveMessage(parent);
}
catch (AssemblyResolutionException)
{
// this can happen for plugins.
//Console.WriteLine("AssemblyResolutionException: "+ ex.ToString());
- break;
}
+
+ // process this
+ MessageClassProcessor.Process(td);
+ modified = true;
}
// check for embedded types
foreach (TypeDefinition embedded in td.NestedTypes)
{
- didWork |= CheckMessageBase(embedded);
+ modified |= WeaveMessage(embedded);
}
- return didWork;
+ return modified;
}
- static bool CheckSyncList(TypeDefinition td)
+ static bool WeaveSyncObject(TypeDefinition td)
{
- if (!td.IsClass)
+ bool modified = false;
+
+ // ignore generic classes
+ // we can not process generic classes
+ // we give error if a generic syncObject is used in NetworkBehaviour
+ if (td.HasGenericParameters)
return false;
- bool didWork = false;
+ // ignore abstract classes
+ // we dont need to process abstract classes because classes that
+ // inherit from them will be processed instead
- // are ANY parent classes SyncListStruct
- TypeReference parent = td.BaseType;
- while (parent != null)
+ // We cant early return with non classes or Abstract classes
+ // because we still need to check for embeded types
+ if (td.IsClass || !td.IsAbstract)
{
- if (parent.FullName.StartsWith(SyncListType.FullName, StringComparison.Ordinal))
+ if (td.IsDerivedFrom(SyncListType))
{
- SyncListProcessor.Process(td);
- didWork = true;
- break;
+ SyncListProcessor.Process(td, SyncListType);
+ modified = true;
}
- if (parent.FullName.StartsWith(SyncSetType.FullName, StringComparison.Ordinal))
+ else if (td.IsDerivedFrom(SyncSetType))
{
- SyncListProcessor.Process(td);
- didWork = true;
- break;
+ SyncListProcessor.Process(td, SyncSetType);
+ modified = true;
}
- if (parent.FullName.StartsWith(SyncDictionaryType.FullName, StringComparison.Ordinal))
+ else if (td.IsDerivedFrom(SyncDictionaryType))
{
SyncDictionaryProcessor.Process(td);
- didWork = true;
- break;
- }
- try
- {
- parent = parent.Resolve().BaseType;
- }
- catch (AssemblyResolutionException)
- {
- // this can happen for pluins.
- //Console.WriteLine("AssemblyResolutionException: "+ ex.ToString());
- break;
+ modified = true;
}
}
// check for embedded types
foreach (TypeDefinition embedded in td.NestedTypes)
{
- didWork |= CheckSyncList(embedded);
+ modified |= WeaveSyncObject(embedded);
}
- return didWork;
+ return modified;
}
static bool Weave(string assName, IEnumerable dependencies, string unityEngineDLLPath, string mirrorNetDLLPath, string outputDir)
@@ -469,7 +484,7 @@ static bool Weave(string assName, IEnumerable dependencies, string unity
using (CurrentAssembly = AssemblyDefinition.ReadAssembly(assName, new ReaderParameters { ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver }))
{
asmResolver.AddSearchDirectory(Path.GetDirectoryName(assName));
- asmResolver.AddSearchDirectory(Helpers.UnityEngineDLLDirectoryName());
+ asmResolver.AddSearchDirectory(Helpers.UnityEngineDllDirectoryName());
asmResolver.AddSearchDirectory(Path.GetDirectoryName(unityEngineDLLPath));
asmResolver.AddSearchDirectory(Path.GetDirectoryName(mirrorNetDLLPath));
if (dependencies != null)
@@ -489,46 +504,14 @@ static bool Weave(string assName, IEnumerable dependencies, string unity
ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
Console.WriteLine("Script Module: {0}", moduleDefinition.Name);
- // Process each NetworkBehaviour
- bool didWork = false;
+ bool modified = WeaveModule(moduleDefinition);
- // We need to do 2 passes, because SyncListStructs might be referenced from other modules, so we must make sure we generate them first.
- for (int pass = 0; pass < 2; pass++)
+ if (WeavingFailed)
{
- System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
- foreach (TypeDefinition td in moduleDefinition.Types)
- {
- if (td.IsClass && td.BaseType.CanBeResolved())
- {
- try
- {
- if (pass == 0)
- {
- didWork |= CheckSyncList(td);
- }
- else
- {
- didWork |= CheckNetworkBehaviour(td);
- didWork |= CheckMessageBase(td);
- }
- }
- catch (Exception ex)
- {
- Error(ex.ToString());
- throw ex;
- }
- }
-
- if (WeavingFailed)
- {
- return false;
- }
- }
- watch.Stop();
- Console.WriteLine("Pass: " + pass + " took " + watch.ElapsedMilliseconds + " milliseconds");
+ return false;
}
- if (didWork)
+ if (modified)
{
// this must be done for ALL code, not just NetworkBehaviours
try
@@ -543,7 +526,6 @@ static bool Weave(string assName, IEnumerable dependencies, string unity
if (WeavingFailed)
{
- //Log.Error("Failed phase II.");
return false;
}
@@ -563,6 +545,45 @@ static bool Weave(string assName, IEnumerable dependencies, string unity
return true;
}
+ static bool WeaveModule(ModuleDefinition moduleDefinition)
+ {
+ try
+ {
+ bool modified = false;
+
+ // We need to do 2 passes, because SyncListStructs might be referenced from other modules, so we must make sure we generate them first.
+ System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
+ foreach (TypeDefinition td in moduleDefinition.Types)
+ {
+ if (td.IsClass && td.BaseType.CanBeResolved())
+ {
+ modified |= WeaveSyncObject(td);
+ }
+ }
+ watch.Stop();
+ Console.WriteLine("Weave sync objects took " + watch.ElapsedMilliseconds + " milliseconds");
+
+ watch.Start();
+ foreach (TypeDefinition td in moduleDefinition.Types)
+ {
+ if (td.IsClass && td.BaseType.CanBeResolved())
+ {
+ modified |= WeaveNetworkBehavior(td);
+ modified |= WeaveMessage(td);
+ }
+ }
+ watch.Stop();
+ Console.WriteLine("Weave behaviours and messages took" + watch.ElapsedMilliseconds + " milliseconds");
+
+ return modified;
+ }
+ catch (Exception ex)
+ {
+ Error(ex.ToString());
+ throw;
+ }
+ }
+
public static bool WeaveAssemblies(IEnumerable assemblies, IEnumerable dependencies, string outputDir, string unityEngineDLLPath, string mirrorNetDLLPath)
{
WeavingFailed = false;
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Writers.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Writers.cs
index 040960d..ece8b13 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Writers.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Editor/Weaver/Writers.cs
@@ -24,24 +24,62 @@ public static void Register(TypeReference dataType, MethodReference methodRefere
public static MethodReference GetWriteFunc(TypeReference variable, int recursionCount = 0)
{
if (writeFuncs.TryGetValue(variable.FullName, out MethodReference foundFunc))
- {
+ {
return foundFunc;
}
+ MethodDefinition newWriterFunc;
+
+ // Arrays are special, if we resolve them, we get the element type,
+ // so the following ifs might choke on it for scriptable objects
+ // or other objects that require a custom serializer
+ // thus check if it is an array and skip all the checks.
+ if (variable.IsArray)
+ {
+ newWriterFunc = GenerateArrayWriteFunc(variable, recursionCount);
+ RegisterWriteFunc(variable.FullName, newWriterFunc);
+ return newWriterFunc;
+ }
+
if (variable.IsByReference)
{
// error??
- Weaver.Error($"{variable} has unsupported type. Use one of Mirror supported types instead");
+ Weaver.Error($"Cannot pass {variable.Name} by reference", variable);
return null;
}
-
- MethodDefinition newWriterFunc;
-
- if (variable.IsArray)
+ TypeDefinition td = variable.Resolve();
+ if (td == null)
{
- newWriterFunc = GenerateArrayWriteFunc(variable, recursionCount);
+ Weaver.Error($"{variable.Name} is not a supported type. Use a supported type or provide a custom writer", variable);
+ return null;
}
- else if (variable.Resolve().IsEnum)
+ if (td.IsDerivedFrom(Weaver.ComponentType))
+ {
+ Weaver.Error($"Cannot generate writer for component type {variable.Name}. Use a supported type or provide a custom writer", variable);
+ return null;
+ }
+ if (variable.FullName == Weaver.ObjectType.FullName)
+ {
+ Weaver.Error($"Cannot generate writer for {variable.Name}. Use a supported type or provide a custom writer", variable);
+ return null;
+ }
+ if (variable.FullName == Weaver.ScriptableObjectType.FullName)
+ {
+ Weaver.Error($"Cannot generate writer for {variable.Name}. Use a supported type or provide a custom writer", variable);
+ return null;
+ }
+ if (td.HasGenericParameters && !td.FullName.StartsWith("System.ArraySegment`1", System.StringComparison.Ordinal))
+ {
+ Weaver.Error($"Cannot generate writer for generic type {variable.Name}. Use a supported type or provide a custom writer", variable);
+ return null;
+ }
+ if (td.IsInterface)
+ {
+ Weaver.Error($"Cannot generate writer for interface {variable.Name}. Use a supported type or provide a custom writer", variable);
+ return null;
+ }
+
+ if (variable.Resolve().IsEnum)
{
return GetWriteFunc(variable.Resolve().GetEnumUnderlyingType(), recursionCount);
}
@@ -51,7 +89,7 @@ public static MethodReference GetWriteFunc(TypeReference variable, int recursion
}
else
{
- newWriterFunc = GenerateStructWriterFunction(variable, recursionCount);
+ newWriterFunc = GenerateClassOrStructWriterFunction(variable, recursionCount);
}
if (newWriterFunc == null)
@@ -72,16 +110,11 @@ static void RegisterWriteFunc(string name, MethodDefinition newWriterFunc)
Weaver.WeaveLists.generateContainerClass.Methods.Add(newWriterFunc);
}
- static MethodDefinition GenerateStructWriterFunction(TypeReference variable, int recursionCount)
+ static MethodDefinition GenerateClassOrStructWriterFunction(TypeReference variable, int recursionCount)
{
if (recursionCount > MaxRecursionCount)
{
- Weaver.Error($"{variable} can't be serialized because it references itself");
- return null;
- }
-
- if (!Weaver.IsValidTypeToGenerate(variable.Resolve()))
- {
+ Weaver.Error($"{variable.Name} can't be serialized because it references itself", variable);
return null;
}
@@ -106,53 +139,56 @@ static MethodDefinition GenerateStructWriterFunction(TypeReference variable, int
ILProcessor worker = writerFunc.Body.GetILProcessor();
- uint fields = 0;
- foreach (FieldDefinition field in variable.Resolve().Fields)
- {
- if (field.IsStatic || field.IsPrivate)
- continue;
-
- if (field.FieldType.Resolve().HasGenericParameters)
- {
- Weaver.Error($"{field} has unsupported type. Create a derived class instead of using generics");
- return null;
- }
+ if (!WriteAllFields(variable, recursionCount, worker))
+ return null;
- if (field.FieldType.Resolve().IsInterface)
- {
- Weaver.Error($"{field} has unsupported type. Use a concrete class instead of an interface");
- return null;
- }
+ worker.Append(worker.Create(OpCodes.Ret));
+ return writerFunc;
+ }
+ ///
+ /// Fiends all fields in
+ ///
+ ///
+ ///
+ ///
+ /// false if fail
+ static bool WriteAllFields(TypeReference variable, int recursionCount, ILProcessor worker)
+ {
+ uint fields = 0;
+ foreach (FieldDefinition field in variable.FindAllPublicFields())
+ {
MethodReference writeFunc = GetWriteFunc(field.FieldType, recursionCount + 1);
if (writeFunc != null)
{
+ FieldReference fieldRef = Weaver.CurrentAssembly.MainModule.ImportReference(field);
+
fields++;
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldarg_1));
- worker.Append(worker.Create(OpCodes.Ldfld, field));
+ worker.Append(worker.Create(OpCodes.Ldfld, fieldRef));
worker.Append(worker.Create(OpCodes.Call, writeFunc));
}
else
{
- Weaver.Error($"{field} has unsupported type. Use a type supported by Mirror instead");
- return null;
+ Weaver.Error($"{field.Name} has unsupported type. Use a type supported by Mirror instead", field);
+ return false;
}
}
+
if (fields == 0)
{
- Log.Warning($" {variable} has no no public or non-static fields to serialize");
+ Log.Warning($"{variable} has no no public or non-static fields to serialize");
}
- worker.Append(worker.Create(OpCodes.Ret));
- return writerFunc;
+
+ return true;
}
static MethodDefinition GenerateArrayWriteFunc(TypeReference variable, int recursionCount)
{
-
if (!variable.IsArrayType())
{
- Weaver.Error($"{variable} is an unsupported type. Jagged and multidimensional arrays are not supported");
+ Weaver.Error($"{variable.Name} is an unsupported type. Jagged and multidimensional arrays are not supported", variable);
return null;
}
@@ -231,13 +267,11 @@ static MethodDefinition GenerateArrayWriteFunc(TypeReference variable, int recur
worker.Append(worker.Create(OpCodes.Ldobj, variable.GetElementType()));
worker.Append(worker.Create(OpCodes.Call, elementWriteFunc));
-
worker.Append(worker.Create(OpCodes.Ldloc_1));
worker.Append(worker.Create(OpCodes.Ldc_I4_1));
worker.Append(worker.Create(OpCodes.Add));
worker.Append(worker.Create(OpCodes.Stloc_1));
-
// end for loop
worker.Append(labelHead);
worker.Append(worker.Create(OpCodes.Ldloc_1));
@@ -295,7 +329,7 @@ static MethodDefinition GenerateArraySegmentWriteFunc(TypeReference variable, in
worker.Append(worker.Create(OpCodes.Call, countref));
worker.Append(worker.Create(OpCodes.Stloc_0));
-
+
// writer.WritePackedInt32(length);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldloc_0));
@@ -303,7 +337,7 @@ static MethodDefinition GenerateArraySegmentWriteFunc(TypeReference variable, in
// Loop through the ArraySegment and call the writer for each element.
// generates this:
- // for (int i=0; i< length; i++)
+ // for (int i=0; i< length; i++)
// {
// writer.Write(value.Array[i + value.Offset]);
// }
@@ -315,32 +349,31 @@ static MethodDefinition GenerateArraySegmentWriteFunc(TypeReference variable, in
// loop body
Instruction labelBody = worker.Create(OpCodes.Nop);
worker.Append(labelBody);
- {
- // writer.Write(value.Array[i + value.Offset]);
- worker.Append(worker.Create(OpCodes.Ldarg_0));
- worker.Append(worker.Create(OpCodes.Ldarga_S, (byte)1));
- worker.Append(worker.Create(OpCodes.Call, Weaver.ArraySegmentArrayReference.MakeHostInstanceGeneric(genericInstance)));
- worker.Append(worker.Create(OpCodes.Ldloc_1));
- worker.Append(worker.Create(OpCodes.Ldarga_S, (byte)1));
- worker.Append(worker.Create(OpCodes.Call, Weaver.ArraySegmentOffsetReference.MakeHostInstanceGeneric(genericInstance)));
- worker.Append(worker.Create(OpCodes.Add));
- worker.Append(worker.Create(OpCodes.Ldelema, elementType));
- worker.Append(worker.Create(OpCodes.Ldobj, elementType));
- worker.Append(worker.Create(OpCodes.Call, elementWriteFunc));
- }
+
+ // writer.Write(value.Array[i + value.Offset]);
+ worker.Append(worker.Create(OpCodes.Ldarg_0));
+ worker.Append(worker.Create(OpCodes.Ldarga_S, (byte)1));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.ArraySegmentArrayReference.MakeHostInstanceGeneric(genericInstance)));
+ worker.Append(worker.Create(OpCodes.Ldloc_1));
+ worker.Append(worker.Create(OpCodes.Ldarga_S, (byte)1));
+ worker.Append(worker.Create(OpCodes.Call, Weaver.ArraySegmentOffsetReference.MakeHostInstanceGeneric(genericInstance)));
+ worker.Append(worker.Create(OpCodes.Add));
+ worker.Append(worker.Create(OpCodes.Ldelema, elementType));
+ worker.Append(worker.Create(OpCodes.Ldobj, elementType));
+ worker.Append(worker.Create(OpCodes.Call, elementWriteFunc));
+
worker.Append(worker.Create(OpCodes.Ldloc_1));
worker.Append(worker.Create(OpCodes.Ldc_I4_1));
worker.Append(worker.Create(OpCodes.Add));
worker.Append(worker.Create(OpCodes.Stloc_1));
-
// end for loop
worker.Append(labelHead);
worker.Append(worker.Create(OpCodes.Ldloc_1));
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Blt, labelBody));
-
+
// return
worker.Append(worker.Create(OpCodes.Ret));
return writerFunc;
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/AnimationControllers/Tank.controller b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/AnimationControllers/Tank.controller
deleted file mode 100644
index 5a7f506..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/AnimationControllers/Tank.controller
+++ /dev/null
@@ -1,156 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!91 &9100000
-AnimatorController:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Tank
- serializedVersion: 5
- m_AnimatorParameters:
- - m_Name: Fire
- m_Type: 9
- m_DefaultFloat: 0
- m_DefaultInt: 0
- m_DefaultBool: 0
- m_Controller: {fileID: 0}
- m_AnimatorLayers:
- - serializedVersion: 5
- m_Name: Base Layer
- m_StateMachine: {fileID: 1107206089488630588}
- m_Mask: {fileID: 0}
- m_Motions: []
- m_Behaviours: []
- m_BlendingMode: 0
- m_SyncedLayerIndex: -1
- m_DefaultWeight: 0
- m_IKPass: 0
- m_SyncedLayerAffectsTiming: 0
- m_Controller: {fileID: 9100000}
---- !u!1101 &1101845105868117086
-AnimatorStateTransition:
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name:
- m_Conditions:
- - m_ConditionMode: 1
- m_ConditionEvent: Fire
- m_EventTreshold: 0
- m_DstStateMachine: {fileID: 0}
- m_DstState: {fileID: 1102477577393645330}
- m_Solo: 0
- m_Mute: 0
- m_IsExit: 0
- serializedVersion: 3
- m_TransitionDuration: 0.25
- m_TransitionOffset: 0
- m_ExitTime: 0.45454544
- m_HasExitTime: 0
- m_HasFixedDuration: 1
- m_InterruptionSource: 0
- m_OrderedInterruption: 1
- m_CanTransitionToSelf: 1
---- !u!1101 &1101857281332299900
-AnimatorStateTransition:
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name:
- m_Conditions: []
- m_DstStateMachine: {fileID: 0}
- m_DstState: {fileID: 1102845660080023070}
- m_Solo: 0
- m_Mute: 0
- m_IsExit: 0
- serializedVersion: 3
- m_TransitionDuration: 0.058695674
- m_TransitionOffset: 0.41739127
- m_ExitTime: 0.9060869
- m_HasExitTime: 1
- m_HasFixedDuration: 1
- m_InterruptionSource: 0
- m_OrderedInterruption: 1
- m_CanTransitionToSelf: 1
---- !u!1102 &1102477577393645330
-AnimatorState:
- serializedVersion: 5
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Recon_Tank_Rig|Shoot
- m_Speed: 1
- m_CycleOffset: 0
- m_Transitions:
- - {fileID: 1101857281332299900}
- m_StateMachineBehaviours: []
- m_Position: {x: 50, y: 50, z: 0}
- m_IKOnFeet: 0
- m_WriteDefaultValues: 1
- m_Mirror: 0
- m_SpeedParameterActive: 0
- m_MirrorParameterActive: 0
- m_CycleOffsetParameterActive: 0
- m_TimeParameterActive: 0
- m_Motion: {fileID: 7400006, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- m_Tag:
- m_SpeedParameter:
- m_MirrorParameter:
- m_CycleOffsetParameter:
- m_TimeParameter:
---- !u!1102 &1102845660080023070
-AnimatorState:
- serializedVersion: 5
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Recon_Tank_Rig|Idle
- m_Speed: 1
- m_CycleOffset: 0
- m_Transitions:
- - {fileID: 1101845105868117086}
- m_StateMachineBehaviours: []
- m_Position: {x: 50, y: 50, z: 0}
- m_IKOnFeet: 0
- m_WriteDefaultValues: 1
- m_Mirror: 0
- m_SpeedParameterActive: 0
- m_MirrorParameterActive: 0
- m_CycleOffsetParameterActive: 0
- m_TimeParameterActive: 0
- m_Motion: {fileID: 7400004, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- m_Tag:
- m_SpeedParameter:
- m_MirrorParameter:
- m_CycleOffsetParameter:
- m_TimeParameter:
---- !u!1107 &1107206089488630588
-AnimatorStateMachine:
- serializedVersion: 5
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Base Layer
- m_ChildStates:
- - serializedVersion: 1
- m_State: {fileID: 1102845660080023070}
- m_Position: {x: 132, y: 300, z: 0}
- - serializedVersion: 1
- m_State: {fileID: 1102477577393645330}
- m_Position: {x: 360, y: 432, z: 0}
- m_ChildStateMachines: []
- m_AnyStateTransitions: []
- m_EntryTransitions: []
- m_StateMachineTransitions: {}
- m_StateMachineBehaviours: []
- m_AnyStatePosition: {x: 50, y: 20, z: 0}
- m_EntryPosition: {x: 50, y: 120, z: 0}
- m_ExitPosition: {x: 800, y: 120, z: 0}
- m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
- m_DefaultState: {fileID: 1102845660080023070}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/AnimationControllers/Tank.controller.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/AnimationControllers/Tank.controller.meta
deleted file mode 100644
index b4df009..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/AnimationControllers/Tank.controller.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: e0dbc8b2f2711a54f9b7ed1358a4c6af
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 9100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Capsule.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Capsule.mat
deleted file mode 100644
index 09a4fa2..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Capsule.mat
+++ /dev/null
@@ -1,77 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Capsule
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0.5
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 0, g: 0.07727194, b: 1, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Capsule.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Capsule.mat.meta
deleted file mode 100644
index b202aa9..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Capsule.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 3ec90781e3720544da7fc86055e6cbe6
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cube.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cube.mat
deleted file mode 100644
index f7e2181..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cube.mat
+++ /dev/null
@@ -1,77 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Cube
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0.5
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 1, g: 0.93989503, b: 0, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cube.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cube.mat.meta
deleted file mode 100644
index 9c096c8..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cube.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 1d5f3015968dad04780bf9d2113cc772
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cylinder.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cylinder.mat
deleted file mode 100644
index 59d5192..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cylinder.mat
+++ /dev/null
@@ -1,77 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Cylinder
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0.5
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 0, g: 0.5943396, b: 0.054526776, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cylinder.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cylinder.mat.meta
deleted file mode 100644
index 00cc85e..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Cylinder.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 439a10ee8f8d14040be9003239449741
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Player.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Player.mat
deleted file mode 100644
index d16a481..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Player.mat
+++ /dev/null
@@ -1,77 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Player
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0.5
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 0, g: 0, b: 0, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Player.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Player.mat.meta
deleted file mode 100644
index 56884a4..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Player.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 792117fe9a386a8489e8010bec746339
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Quad.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Quad.mat
deleted file mode 100644
index 060786b..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Quad.mat
+++ /dev/null
@@ -1,77 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Quad
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0.5
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 0.8207547, g: 0.8207547, b: 0.8207547, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Quad.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Quad.mat.meta
deleted file mode 100644
index be7d0db..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Quad.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 6eb3f3ba66756364d8b94e662e7e8af5
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Shelter.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Shelter.mat
deleted file mode 100644
index 73ef86d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Shelter.mat
+++ /dev/null
@@ -1,77 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Shelter
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0.5
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 0.8018868, g: 0.52244145, b: 0, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Shelter.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Shelter.mat.meta
deleted file mode 100644
index c261931..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Shelter.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: aef230244d219314fb8453f0365b8176
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Sphere.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Sphere.mat
deleted file mode 100644
index 4358e1b..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Sphere.mat
+++ /dev/null
@@ -1,77 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Sphere
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0.5
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 0.9716981, g: 0, b: 0.77970594, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Sphere.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Sphere.mat.meta
deleted file mode 100644
index 8822215..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Sphere.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 58936713efca1ec488624ee297b5d687
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Zone.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Zone.mat
deleted file mode 100644
index 38e8f91..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Zone.mat
+++ /dev/null
@@ -1,78 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Zone
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords: _ALPHAPREMULTIPLY_ON
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: 3000
- stringTagMap:
- RenderType: Transparent
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 10
- - _GlossMapScale: 1
- - _Glossiness: 0
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 3
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 0
- m_Colors:
- - _Color: {r: 0, g: 0, b: 0, a: 0.039215688}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Zone.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Zone.mat.meta
deleted file mode 100644
index 4cfbe95..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Materials/Zone.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: a7c679cf124f7ae46a0291ea35848554
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs.meta
deleted file mode 100644
index 37601bf..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 2be4f78570b2a1e4cae84466d35d606c
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Capsule.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Capsule.prefab
deleted file mode 100644
index 4765d1e..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Capsule.prefab
+++ /dev/null
@@ -1,133 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &1076878374699499732
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1076878374699499735}
- - component: {fileID: 1076878374699499728}
- - component: {fileID: 1076878374699499729}
- - component: {fileID: 1076878374699499734}
- - component: {fileID: 2648107611936813301}
- - component: {fileID: 5697694911122891659}
- m_Layer: 0
- m_Name: Capsule
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1076878374699499735
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1076878374699499732}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 20, y: 1, z: -20}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &1076878374699499728
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1076878374699499732}
- m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &1076878374699499729
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1076878374699499732}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 3ec90781e3720544da7fc86055e6cbe6, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!136 &1076878374699499734
-CapsuleCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1076878374699499732}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- m_Radius: 0.5
- m_Height: 2
- m_Direction: 1
- m_Center: {x: 0, y: 0, z: 0}
---- !u!114 &2648107611936813301
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1076878374699499732}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 0
- m_AssetId: e1971f4a8c7661546bc509b44bd91b80
- m_SceneId: 0
---- !u!114 &5697694911122891659
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1076878374699499732}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 1731d8de2d0c84333b08ebe1e79f4118, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- visRange: 5
- visUpdateInterval: 0.1
- checkMethod: 0
- forceHidden: 0
- castLayers:
- serializedVersion: 2
- m_Bits: 512
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Capsule.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Capsule.prefab.meta
deleted file mode 100644
index 99fb5c0..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Capsule.prefab.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: e1971f4a8c7661546bc509b44bd91b80
-PrefabImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Cube.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Cube.prefab
deleted file mode 100644
index b626be6..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Cube.prefab
+++ /dev/null
@@ -1,132 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &5623359707189648430
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 5623359707189648426}
- - component: {fileID: 5623359707189648427}
- - component: {fileID: 5623359707189648424}
- - component: {fileID: 5623359707189648425}
- - component: {fileID: 5623359707189648404}
- - component: {fileID: 5623359707189648405}
- m_Layer: 0
- m_Name: Cube
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &5623359707189648426
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5623359707189648430}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1, z: 2}
- m_LocalScale: {x: 2, y: 2, z: 2}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &5623359707189648427
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5623359707189648430}
- m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &5623359707189648424
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5623359707189648430}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 1d5f3015968dad04780bf9d2113cc772, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!65 &5623359707189648425
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5623359707189648430}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Size: {x: 1, y: 1, z: 1}
- m_Center: {x: 0, y: 0, z: 0}
---- !u!114 &5623359707189648404
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5623359707189648430}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 0
- m_AssetId: 4ff300cf6bb3c6342a9552c4f18788c8
- m_SceneId: 0
---- !u!114 &5623359707189648405
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5623359707189648430}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 1731d8de2d0c84333b08ebe1e79f4118, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- visRange: 5
- visUpdateInterval: 0.1
- checkMethod: 0
- forceHidden: 0
- castLayers:
- serializedVersion: 2
- m_Bits: 512
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Cube.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Cube.prefab.meta
deleted file mode 100644
index 8b53f72..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Cube.prefab.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 4ff300cf6bb3c6342a9552c4f18788c8
-PrefabImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Cylinder.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Cylinder.prefab
deleted file mode 100644
index 5b6f649..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Cylinder.prefab
+++ /dev/null
@@ -1,133 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &6852530814182375312
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 6852530814182375316}
- - component: {fileID: 6852530814182375315}
- - component: {fileID: 6852530814182375314}
- - component: {fileID: 6852530814182375313}
- - component: {fileID: 6852530814182375318}
- - component: {fileID: 6852530814182375317}
- m_Layer: 0
- m_Name: Cylinder
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &6852530814182375316
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6852530814182375312}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: -2, y: 1, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &6852530814182375315
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6852530814182375312}
- m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &6852530814182375314
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6852530814182375312}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 439a10ee8f8d14040be9003239449741, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!136 &6852530814182375313
-CapsuleCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6852530814182375312}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- m_Radius: 0.5
- m_Height: 2
- m_Direction: 1
- m_Center: {x: 0, y: 0, z: 0}
---- !u!114 &6852530814182375318
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6852530814182375312}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 0
- m_AssetId: 12a4c14e672c00b4b840f937d824b890
- m_SceneId: 0
---- !u!114 &6852530814182375317
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6852530814182375312}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 1731d8de2d0c84333b08ebe1e79f4118, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- visRange: 5
- visUpdateInterval: 0.1
- checkMethod: 0
- forceHidden: 0
- castLayers:
- serializedVersion: 2
- m_Bits: 512
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Player.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Player.prefab
deleted file mode 100644
index 41e8ab9..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Player.prefab
+++ /dev/null
@@ -1,235 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &5815001218983416211
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 3254954141432383832}
- - component: {fileID: 1800893346221236401}
- - component: {fileID: 136369082707552984}
- m_Layer: 0
- m_Name: Visor
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &3254954141432383832
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5815001218983416211}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0.39999998, z: 0.505}
- m_LocalScale: {x: 0.5, y: 0.099999994, z: 0.19999999}
- m_Children: []
- m_Father: {fileID: 5328458565928408179}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &1800893346221236401
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5815001218983416211}
- m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &136369082707552984
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5815001218983416211}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 4294967295
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!1 &8872462076811691049
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 5328458565928408179}
- - component: {fileID: 7482234573209362796}
- - component: {fileID: 8972496075962964235}
- - component: {fileID: 8993127209816276930}
- - component: {fileID: 8537344390966522168}
- - component: {fileID: 8704659178864205755}
- - component: {fileID: 887491563423388292}
- m_Layer: 9
- m_Name: Player
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &5328458565928408179
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 8872462076811691049}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1.08, z: -20}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 3254954141432383832}
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &7482234573209362796
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 8872462076811691049}
- m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &8972496075962964235
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 8872462076811691049}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 792117fe9a386a8489e8010bec746339, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!143 &8993127209816276930
-CharacterController:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 8872462076811691049}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Height: 2
- m_Radius: 0.5
- m_SlopeLimit: 45
- m_StepOffset: 0.3
- m_SkinWidth: 0.08
- m_MinMoveDistance: 0.001
- m_Center: {x: 0, y: 0, z: 0}
---- !u!114 &8537344390966522168
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 8872462076811691049}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 1
- m_AssetId: a5bdca0a2315d43499be7dcef473fbc7
- m_SceneId: 0
---- !u!114 &8704659178864205755
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 8872462076811691049}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: e8f68561248aaca4fb96847ce24742ee, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0
- moveSpeed: 8
- turnSpeedAccel: 5
- turnSpeedDecel: 5
- maxTurnSpeed: 150
- jumpSpeed: 0
- jumpFactor: 0.025
- horizontal: 0
- vertical: 0
- turn: 0
- isGrounded: 1
- isFalling: 0
---- !u!114 &887491563423388292
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 8872462076811691049}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0
- compressRotation: 1
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Player.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Player.prefab.meta
deleted file mode 100644
index b91d19d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Player.prefab.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: a5bdca0a2315d43499be7dcef473fbc7
-PrefabImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Sphere.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Sphere.prefab
deleted file mode 100644
index ae30f8f..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Sphere.prefab
+++ /dev/null
@@ -1,132 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &855244094988030905
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 855244094988030909}
- - component: {fileID: 855244094988030906}
- - component: {fileID: 855244094988030907}
- - component: {fileID: 855244094988030904}
- - component: {fileID: 855244094988030911}
- - component: {fileID: 855244094988030908}
- m_Layer: 0
- m_Name: Sphere
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &855244094988030909
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 855244094988030905}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 2, y: 1, z: 0}
- m_LocalScale: {x: 2, y: 2, z: 2}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &855244094988030906
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 855244094988030905}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &855244094988030907
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 855244094988030905}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 58936713efca1ec488624ee297b5d687, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!135 &855244094988030904
-SphereCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 855244094988030905}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Radius: 0.5
- m_Center: {x: 0, y: 0, z: 0}
---- !u!114 &855244094988030911
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 855244094988030905}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 0
- m_AssetId: f6d08eb9a8e35d84fa30a7e3ae64181a
- m_SceneId: 0
---- !u!114 &855244094988030908
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 855244094988030905}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 1731d8de2d0c84333b08ebe1e79f4118, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- visRange: 5
- visUpdateInterval: 0.1
- checkMethod: 0
- forceHidden: 0
- castLayers:
- serializedVersion: 2
- m_Bits: 512
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Sphere.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Sphere.prefab.meta
deleted file mode 100644
index 0fb6a41..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Sphere.prefab.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: f6d08eb9a8e35d84fa30a7e3ae64181a
-PrefabImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Tank.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Tank.prefab
deleted file mode 100644
index 6d7aa37..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Tank.prefab
+++ /dev/null
@@ -1,599 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &160176457
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 160176456}
- - component: {fileID: 160176460}
- - component: {fileID: 160176459}
- - component: {fileID: 160176458}
- - component: {fileID: 160176461}
- - component: {fileID: 160176462}
- m_Layer: 0
- m_Name: Tank
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &160176456
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 160176457}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: -20, y: 0, z: -20}
- m_LocalScale: {x: 5, y: 5, z: 5}
- m_Children:
- - {fileID: 3234001708628876000}
- - {fileID: 1042389410631263445}
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!95 &160176460
-Animator:
- serializedVersion: 3
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 160176457}
- m_Enabled: 1
- m_Avatar: {fileID: 9000000, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- m_Controller: {fileID: 9100000, guid: e0dbc8b2f2711a54f9b7ed1358a4c6af, type: 2}
- m_CullingMode: 1
- m_UpdateMode: 0
- m_ApplyRootMotion: 0
- m_LinearVelocityBlending: 0
- m_WarningMessage:
- m_HasTransformHierarchy: 1
- m_AllowConstantClipSamplingOptimization: 1
- m_KeepAnimatorControllerStateOnDisable: 0
---- !u!114 &160176459
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 160176457}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 0
- m_AssetId: ab222ed73ada1ac4ba2f61e843d7627c
- m_SceneId: 0
---- !u!114 &160176458
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 160176457}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 1731d8de2d0c84333b08ebe1e79f4118, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- visRange: 10
- visUpdateInterval: 0.1
- checkMethod: 0
- forceHidden: 0
- castLayers:
- serializedVersion: 2
- m_Bits: 512
---- !u!114 &160176461
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 160176457}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 7f6f3bf89aa97405989c802ba270f815, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- animator: {fileID: 160176460}
---- !u!114 &160176462
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 160176457}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 7a25c54cd35eb284eb6b8ed19cf60443, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- rotation: {x: 0, y: 0, z: 0, w: 0}
- turnSpeed: 0.1
---- !u!1 &489699669850839237
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 6048638457609172120}
- m_Layer: 0
- m_Name: Wheel_Rear_L_end
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &6048638457609172120
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 489699669850839237}
- m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -0, y: 0.0021921142, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 5371032128924763904}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &739025013192983599
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1766344861363284577}
- m_Layer: 0
- m_Name: Wheel_Middle_L
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1766344861363284577
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 739025013192983599}
- m_LocalRotation: {x: -0.5, y: 0.5, z: 0.49999994, w: 0.50000006}
- m_LocalPosition: {x: -0, y: 0.0011627917, z: 0.0000000010728836}
- m_LocalScale: {x: 1, y: 0.99999994, z: 1}
- m_Children:
- - {fileID: 9163197381092130014}
- m_Father: {fileID: 847897825935598517}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1014401586714983030
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 7755980514232685276}
- m_Layer: 0
- m_Name: Turret
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &7755980514232685276
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1014401586714983030}
- m_LocalRotation: {x: 0, y: -0.000000119209275, z: -0, w: 1}
- m_LocalPosition: {x: -0, y: 0.0010293524, z: 0}
- m_LocalScale: {x: 1, y: 0.99999994, z: 1}
- m_Children:
- - {fileID: 1517159280684637724}
- m_Father: {fileID: 1703734463393124925}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1218215768088827738
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 5371032128924763904}
- m_Layer: 0
- m_Name: Wheel_Rear_L
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &5371032128924763904
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1218215768088827738}
- m_LocalRotation: {x: -0.5, y: 0.5, z: 0.49999994, w: 0.50000006}
- m_LocalPosition: {x: -0, y: 0.0011627917, z: -0.0026999994}
- m_LocalScale: {x: 1, y: 0.99999994, z: 1}
- m_Children:
- - {fileID: 6048638457609172120}
- m_Father: {fileID: 847897825935598517}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &2620739405153902494
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 7509984371715941402}
- m_Layer: 0
- m_Name: Barrel_end
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &7509984371715941402
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2620739405153902494}
- m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -0, y: 0.0063666296, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1517159280684637724}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &4300763244710219681
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 3234001708628876000}
- - component: {fileID: 2715744559599808281}
- - component: {fileID: 4300454509241183841}
- m_Layer: 0
- m_Name: Recon_Tank
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &3234001708628876000
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 4300763244710219681}
- m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067}
- m_LocalPosition: {x: -0, y: 0, z: 0}
- m_LocalScale: {x: 100, y: 100, z: 100}
- m_Children: []
- m_Father: {fileID: 160176456}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!137 &2715744559599808281
-SkinnedMeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 4300763244710219681}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 2e67e42170aa64aa9a33424f8045ac89, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- serializedVersion: 2
- m_Quality: 0
- m_UpdateWhenOffscreen: 0
- m_SkinnedMotionVectors: 1
- m_Mesh: {fileID: 4300000, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- m_Bones:
- - {fileID: 847897825935598517}
- - {fileID: 1703734463393124925}
- - {fileID: 7755980514232685276}
- - {fileID: 1517159280684637724}
- - {fileID: 7124543900430328667}
- - {fileID: 1766344861363284577}
- - {fileID: 5371032128924763904}
- m_BlendShapeWeights: []
- m_RootBone: {fileID: 847897825935598517}
- m_AABB:
- m_Center: {x: 0, y: 0.0041689305, z: 0.0018957809}
- m_Extent: {x: 0.0028734768, y: 0.004266139, z: 0.006842426}
- m_DirtyAABB: 0
---- !u!64 &4300454509241183841
-MeshCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 4300763244710219681}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 3
- m_Convex: 0
- m_CookingOptions: 14
- m_Mesh: {fileID: 4300000, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
---- !u!1 &4728827432125738153
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 847897825935598517}
- m_Layer: 0
- m_Name: Root
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &847897825935598517
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 4728827432125738153}
- m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071067}
- m_LocalPosition: {x: -0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 1703734463393124925}
- - {fileID: 7124543900430328667}
- - {fileID: 1766344861363284577}
- - {fileID: 5371032128924763904}
- m_Father: {fileID: 1042389410631263445}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &5311698857118067376
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 7124543900430328667}
- m_Layer: 0
- m_Name: Wheel_Front_L
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &7124543900430328667
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5311698857118067376}
- m_LocalRotation: {x: -0.5, y: 0.5, z: 0.49999994, w: 0.50000006}
- m_LocalPosition: {x: -0, y: 0.0011627917, z: 0.0027000008}
- m_LocalScale: {x: 1, y: 0.99999994, z: 1}
- m_Children:
- - {fileID: 5752532462053122769}
- m_Father: {fileID: 847897825935598517}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &5804173475777962202
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1703734463393124925}
- m_Layer: 0
- m_Name: Chasis
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1703734463393124925
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5804173475777962202}
- m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -0, y: 0.0015, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 7755980514232685276}
- m_Father: {fileID: 847897825935598517}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &6536093484198670798
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1517159280684637724}
- m_Layer: 0
- m_Name: Barrel
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1517159280684637724
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 6536093484198670798}
- m_LocalRotation: {x: 0.00000017845065, y: 0.7071068, z: 0.7071067, w: 0.000000009863265}
- m_LocalPosition: {x: 5.6542865e-10, y: 0.0015793034, z: 0.00237158}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 7509984371715941402}
- m_Father: {fileID: 7755980514232685276}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &7509875135952387032
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1042389410631263445}
- m_Layer: 0
- m_Name: Recon_Tank_Rig
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1042389410631263445
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 7509875135952387032}
- m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067}
- m_LocalPosition: {x: -0, y: 0, z: 0}
- m_LocalScale: {x: 100, y: 100, z: 100}
- m_Children:
- - {fileID: 847897825935598517}
- m_Father: {fileID: 160176456}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &7895955422738415095
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 5752532462053122769}
- m_Layer: 0
- m_Name: Wheel_Front_L_end
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &5752532462053122769
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 7895955422738415095}
- m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -0, y: 0.0021921142, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 7124543900430328667}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &8824818431311294599
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 9163197381092130014}
- m_Layer: 0
- m_Name: Wheel_Middle_L_end
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &9163197381092130014
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 8824818431311294599}
- m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -0, y: 0.0021921142, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1766344861363284577}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Tank.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Tank.prefab.meta
deleted file mode 100644
index 9c53dff..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Prefabs/Tank.prefab.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: ab222ed73ada1ac4ba2f61e843d7627c
-PrefabImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/README.md b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/README.md
deleted file mode 100644
index 6c708c2..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Additive Scenes Example
-
-IMPORTANT: Make sure you have a layer in project settings called Player for this example to work well.
-
-In Build Settings, remove all scenes and add all of the scenes from the Examples\AdditiveScenes\Scenes folder in the following order:
-- MainScene
-- SubScene
-
-Open the MainScene in the Editor and make sure the Sub Scenes list in the Network scene object contains the SubScene scene. This is already setup by default, but if the MainScene was opened and saved before putting the scenes in the Build Settings list, the Sub Scenes list may be cleared accidentally.
-
-File -> Build and Run
-
-Start up to 3 built instances: These will all be client players.
-
-Press Play in the Editor and click LAN Host in the editor
-- This will be the host and the 1st player of up to 4. You can also use LAN Server if you prefer.
-
-Click LAN Client in the built instances.
-- WASDQE keys to move & turn your player capsule.
-- There are objects in the corners of the scene hidden by Proximity Checkers.
-- The big area in the middle is where the subscene will be loaded when you get near the shelter.
-- There are also networked objects inside the subscene, also with Proximity Checkers.
-- Since subscenes are only loaded for individual clients, other clients that are outside the middle Zone won't see what those in the subscene can see.
-- If you play a built instance as Host or Server and play as client in the editor, you'll see the subscene content load and unload in the hierarchy as you move in and out of the middle Zone.
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes.meta
deleted file mode 100644
index 79b44f1..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: e989860f377e7764bb7787086ef44ea4
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/MainScene.unity b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/MainScene.unity
deleted file mode 100644
index d4735a2..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/MainScene.unity
+++ /dev/null
@@ -1,2093 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!29 &1
-OcclusionCullingSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_OcclusionBakeSettings:
- smallestOccluder: 5
- smallestHole: 0.25
- backfaceThreshold: 100
- m_SceneGUID: 00000000000000000000000000000000
- m_OcclusionCullingData: {fileID: 0}
---- !u!104 &2
-RenderSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 9
- m_Fog: 0
- m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
- m_FogMode: 3
- m_FogDensity: 0.01
- m_LinearFogStart: 0
- m_LinearFogEnd: 300
- m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
- m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
- m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
- m_AmbientIntensity: 1
- m_AmbientMode: 0
- m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
- m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
- m_HaloStrength: 0.5
- m_FlareStrength: 1
- m_FlareFadeSpeed: 3
- m_HaloTexture: {fileID: 0}
- m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
- m_DefaultReflectionMode: 0
- m_DefaultReflectionResolution: 128
- m_ReflectionBounces: 1
- m_ReflectionIntensity: 1
- m_CustomReflection: {fileID: 0}
- m_Sun: {fileID: 0}
- m_IndirectSpecularColor: {r: 0.4366757, g: 0.48427194, b: 0.5645252, a: 1}
- m_UseRadianceAmbientProbe: 0
---- !u!157 &3
-LightmapSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 11
- m_GIWorkflowMode: 0
- m_GISettings:
- serializedVersion: 2
- m_BounceScale: 1
- m_IndirectOutputScale: 1
- m_AlbedoBoost: 1
- m_EnvironmentLightingMode: 0
- m_EnableBakedLightmaps: 0
- m_EnableRealtimeLightmaps: 0
- m_LightmapEditorSettings:
- serializedVersion: 10
- m_Resolution: 2
- m_BakeResolution: 10
- m_AtlasSize: 512
- m_AO: 0
- m_AOMaxDistance: 1
- m_CompAOExponent: 1
- m_CompAOExponentDirect: 0
- m_Padding: 2
- m_LightmapParameters: {fileID: 0}
- m_LightmapsBakeMode: 1
- m_TextureCompression: 1
- m_FinalGather: 0
- m_FinalGatherFiltering: 1
- m_FinalGatherRayCount: 256
- m_ReflectionCompression: 2
- m_MixedBakeMode: 0
- m_BakeBackend: 0
- m_PVRSampling: 1
- m_PVRDirectSampleCount: 32
- m_PVRSampleCount: 256
- m_PVRBounces: 2
- m_PVRFilterTypeDirect: 0
- m_PVRFilterTypeIndirect: 0
- m_PVRFilterTypeAO: 0
- m_PVRFilteringMode: 1
- m_PVRCulling: 1
- m_PVRFilteringGaussRadiusDirect: 1
- m_PVRFilteringGaussRadiusIndirect: 5
- m_PVRFilteringGaussRadiusAO: 2
- m_PVRFilteringAtrousPositionSigmaDirect: 0.5
- m_PVRFilteringAtrousPositionSigmaIndirect: 2
- m_PVRFilteringAtrousPositionSigmaAO: 1
- m_ShowResolutionOverlay: 1
- m_LightingDataAsset: {fileID: 112000004, guid: b287b2046ddc6af4b9ddc48ab35ca3cb,
- type: 2}
- m_UseShadowmask: 0
---- !u!196 &4
-NavMeshSettings:
- serializedVersion: 2
- m_ObjectHideFlags: 0
- m_BuildSettings:
- serializedVersion: 2
- agentTypeID: 0
- agentRadius: 0.5
- agentHeight: 2
- agentSlope: 45
- agentClimb: 0.4
- ledgeDropHeight: 0
- maxJumpAcrossDistance: 0
- minRegionArea: 2
- manualCellSize: 0
- cellSize: 0.16666667
- manualTileSize: 0
- tileSize: 256
- accuratePlacement: 0
- debug:
- m_Flags: 0
- m_NavMeshData: {fileID: 0}
---- !u!1 &34755345
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 34755346}
- - component: {fileID: 34755348}
- - component: {fileID: 34755347}
- m_Layer: 0
- m_Name: VisibleRangeCapsule
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &34755346
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 34755345}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 20, y: 1, z: -20}
- m_LocalScale: {x: 10, y: 10, z: 10}
- m_Children: []
- m_Father: {fileID: 47225731}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!23 &34755347
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 34755345}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: a7c679cf124f7ae46a0291ea35848554, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &34755348
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 34755345}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1 &47225730
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 47225731}
- m_Layer: 0
- m_Name: ProximityVisualizers
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &47225731
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 47225730}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 1727677799}
- - {fileID: 62078680}
- - {fileID: 34755346}
- - {fileID: 589935541}
- m_Father: {fileID: 909502395}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &62078679
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 62078680}
- - component: {fileID: 62078682}
- - component: {fileID: 62078681}
- m_Layer: 0
- m_Name: VisibleRangeCylinder
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &62078680
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 62078679}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 20, y: 1, z: 20}
- m_LocalScale: {x: 10, y: 10, z: 10}
- m_Children: []
- m_Father: {fileID: 47225731}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!23 &62078681
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 62078679}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: a7c679cf124f7ae46a0291ea35848554, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &62078682
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 62078679}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1 &159607907
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 159607911}
- - component: {fileID: 159607908}
- - component: {fileID: 159607912}
- - component: {fileID: 159607913}
- m_Layer: 9
- m_Name: Zone
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!135 &159607908
-SphereCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 159607907}
- m_Material: {fileID: 0}
- m_IsTrigger: 1
- m_Enabled: 1
- serializedVersion: 2
- m_Radius: 15
- m_Center: {x: 0, y: 0, z: 0}
---- !u!4 &159607911
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 159607907}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 6
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &159607912
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 159607907}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 1
- localPlayerAuthority: 0
- m_AssetId:
- m_SceneId: 1834901131
---- !u!114 &159607913
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 159607907}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 884ed76587eb5854abe6b428b791fdcd, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- subScene: SubScene
---- !u!1001 &160176455
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- m_TransformParent: {fileID: 909502395}
- m_Modifications:
- - target: {fileID: 160176457, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_Name
- value: reconTank
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalPosition.x
- value: -20
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalPosition.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalPosition.z
- value: -20
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalRotation.y
- value: 0.38268343
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalRotation.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalRotation.w
- value: 0.92387956
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_RootOrder
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 45
- objectReference: {fileID: 0}
- - target: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 160176459, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_AssetId
- value: ab222ed73ada1ac4ba2f61e843d7627c
- objectReference: {fileID: 0}
- - target: {fileID: 160176459, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_SceneId
- value: 705590806
- objectReference: {fileID: 0}
- - target: {fileID: 160176459, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- propertyPath: m_LocalPlayerAuthority
- value: 0
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
---- !u!4 &160176456 stripped
-Transform:
- m_CorrespondingSourceObject: {fileID: 160176456, guid: ab222ed73ada1ac4ba2f61e843d7627c,
- type: 3}
- m_PrefabInstance: {fileID: 160176455}
- m_PrefabAsset: {fileID: 0}
---- !u!1 &178547537
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 178547538}
- - component: {fileID: 178547539}
- m_Layer: 0
- m_Name: StartPos
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &178547538
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 178547537}
- m_LocalRotation: {x: 0, y: 1, z: 0, w: 0}
- m_LocalPosition: {x: 0, y: 1.08, z: 20}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1172568542}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0}
---- !u!114 &178547539
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 178547537}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &534669902
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 534669905}
- - component: {fileID: 534669904}
- - component: {fileID: 534669903}
- m_Layer: 0
- m_Name: Main Camera
- m_TagString: MainCamera
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!81 &534669903
-AudioListener:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 534669902}
- m_Enabled: 1
---- !u!20 &534669904
-Camera:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 534669902}
- m_Enabled: 1
- serializedVersion: 2
- m_ClearFlags: 1
- m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
- m_projectionMatrixMode: 1
- m_SensorSize: {x: 36, y: 24}
- m_LensShift: {x: 0, y: 0}
- m_GateFitMode: 2
- m_FocalLength: 50
- m_NormalizedViewPortRect:
- serializedVersion: 2
- x: 0
- y: 0
- width: 1
- height: 1
- near clip plane: 0.3
- far clip plane: 1000
- field of view: 60
- orthographic: 0
- orthographic size: 5
- m_Depth: 0
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_RenderingPath: -1
- m_TargetTexture: {fileID: 0}
- m_TargetDisplay: 0
- m_TargetEye: 3
- m_HDR: 1
- m_AllowMSAA: 1
- m_AllowDynamicResolution: 0
- m_ForceIntoRT: 0
- m_OcclusionCulling: 1
- m_StereoConvergence: 10
- m_StereoSeparation: 0.022
---- !u!4 &534669905
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 534669902}
- m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
- m_LocalPosition: {x: 0, y: 50, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
---- !u!1 &589935540
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 589935541}
- - component: {fileID: 589935543}
- - component: {fileID: 589935542}
- m_Layer: 0
- m_Name: VisibleRangeTank
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &589935541
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 589935540}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -20, y: 1, z: -20}
- m_LocalScale: {x: 20, y: 20, z: 20}
- m_Children: []
- m_Father: {fileID: 47225731}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!23 &589935542
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 589935540}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: a7c679cf124f7ae46a0291ea35848554, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &589935543
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 589935540}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1 &612284967
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 612284968}
- - component: {fileID: 612284971}
- - component: {fileID: 612284970}
- - component: {fileID: 612284969}
- m_Layer: 0
- m_Name: Pillar
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &612284968
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 612284967}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 8, y: 3, z: -8}
- m_LocalScale: {x: 1, y: 3, z: 1}
- m_Children: []
- m_Father: {fileID: 1608696205}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!136 &612284969
-CapsuleCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 612284967}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- m_Radius: 0.5000001
- m_Height: 2
- m_Direction: 1
- m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697}
---- !u!23 &612284970
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 612284967}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: aef230244d219314fb8453f0365b8176, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &612284971
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 612284967}
- m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1 &652875644
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 652875645}
- - component: {fileID: 652875646}
- m_Layer: 0
- m_Name: StartPos
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &652875645
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 652875644}
- m_LocalRotation: {x: 0, y: 0.7071068, z: -0, w: -0.7071068}
- m_LocalPosition: {x: 20, y: 1.08, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1172568542}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 270, z: 0}
---- !u!114 &652875646
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 652875644}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &691846569
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 691846570}
- - component: {fileID: 691846571}
- m_Layer: 0
- m_Name: StartPos
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &691846570
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 691846569}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1.08, z: -20}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1172568542}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &691846571
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 691846569}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1001 &748207074
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- m_TransformParent: {fileID: 909502395}
- m_Modifications:
- - target: {fileID: 855244094988030905, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_Name
- value: Sphere
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalPosition.x
- value: -20
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalPosition.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalPosition.z
- value: 20
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalRotation.y
- value: 0.92387956
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalRotation.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalRotation.w
- value: 0.38268343
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_RootOrder
- value: 2
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 135
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030911, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_AssetId
- value: f6d08eb9a8e35d84fa30a7e3ae64181a
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030911, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_SceneId
- value: 529586728
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: f6d08eb9a8e35d84fa30a7e3ae64181a, type: 3}
---- !u!4 &748207075 stripped
-Transform:
- m_CorrespondingSourceObject: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- m_PrefabInstance: {fileID: 748207074}
- m_PrefabAsset: {fileID: 0}
---- !u!1 &794922164
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 794922165}
- - component: {fileID: 794922168}
- - component: {fileID: 794922167}
- - component: {fileID: 794922166}
- m_Layer: 0
- m_Name: Roof
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &794922165
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 794922164}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 6, z: 0}
- m_LocalScale: {x: 20, y: 0.2, z: 20}
- m_Children: []
- m_Father: {fileID: 1608696205}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!65 &794922166
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 794922164}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Size: {x: 1, y: 1, z: 1}
- m_Center: {x: 0, y: 0, z: 0}
---- !u!23 &794922167
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 794922164}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: aef230244d219314fb8453f0365b8176, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &794922168
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 794922164}
- m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1 &856402103
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 856402104}
- - component: {fileID: 856402107}
- - component: {fileID: 856402106}
- - component: {fileID: 856402105}
- m_Layer: 0
- m_Name: Pillar
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &856402104
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 856402103}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -8, y: 3, z: 8}
- m_LocalScale: {x: 1, y: 3, z: 1}
- m_Children: []
- m_Father: {fileID: 1608696205}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!136 &856402105
-CapsuleCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 856402103}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- m_Radius: 0.5000001
- m_Height: 2
- m_Direction: 1
- m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697}
---- !u!23 &856402106
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 856402103}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: aef230244d219314fb8453f0365b8176, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &856402107
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 856402103}
- m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1001 &901271862
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- m_TransformParent: {fileID: 909502395}
- m_Modifications:
- - target: {fileID: 6852530814182375312, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_Name
- value: Cylinder
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalPosition.x
- value: 20
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalPosition.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalPosition.z
- value: 20
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalRotation.y
- value: 0.9238796
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalRotation.z
- value: -0
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalRotation.w
- value: -0.38268325
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_RootOrder
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 225
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375318, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_SceneId
- value: 568164022
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: 12a4c14e672c00b4b840f937d824b890, type: 3}
---- !u!4 &901271863 stripped
-Transform:
- m_CorrespondingSourceObject: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- m_PrefabInstance: {fileID: 901271862}
- m_PrefabAsset: {fileID: 0}
---- !u!1 &909502394
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 909502395}
- m_Layer: 0
- m_Name: Prefabs
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &909502395
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 909502394}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 160176456}
- - {fileID: 901271863}
- - {fileID: 748207075}
- - {fileID: 1284471874}
- - {fileID: 47225731}
- m_Father: {fileID: 0}
- m_RootOrder: 8
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1047741290
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1047741291}
- - component: {fileID: 1047741294}
- - component: {fileID: 1047741293}
- - component: {fileID: 1047741292}
- m_Layer: 0
- m_Name: Pillar
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &1047741291
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1047741290}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -8, y: 3, z: -8}
- m_LocalScale: {x: 1, y: 3, z: 1}
- m_Children: []
- m_Father: {fileID: 1608696205}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!136 &1047741292
-CapsuleCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1047741290}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- m_Radius: 0.5000001
- m_Height: 2
- m_Direction: 1
- m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697}
---- !u!23 &1047741293
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1047741290}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: aef230244d219314fb8453f0365b8176, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &1047741294
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1047741290}
- m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1 &1172568541
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1172568542}
- m_Layer: 0
- m_Name: StartPositions
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &1172568542
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1172568541}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 178547538}
- - {fileID: 1816951100}
- - {fileID: 652875645}
- - {fileID: 691846570}
- m_Father: {fileID: 0}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!4 &1284471874 stripped
-Transform:
- m_CorrespondingSourceObject: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- m_PrefabInstance: {fileID: 1076878375580925077}
- m_PrefabAsset: {fileID: 0}
---- !u!1 &1405375878
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1405375880}
- - component: {fileID: 1405375879}
- m_Layer: 0
- m_Name: Directional Light
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!108 &1405375879
-Light:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1405375878}
- m_Enabled: 1
- serializedVersion: 8
- m_Type: 1
- m_Color: {r: 0.9622642, g: 0.90969414, b: 0.748932, a: 1}
- m_Intensity: 0.8
- m_Range: 10
- m_SpotAngle: 30
- m_CookieSize: 10
- m_Shadows:
- m_Type: 2
- m_Resolution: -1
- m_CustomResolution: -1
- m_Strength: 0.5
- m_Bias: 0.05
- m_NormalBias: 0.4
- m_NearPlane: 0.2
- m_Cookie: {fileID: 0}
- m_DrawHalo: 0
- m_Flare: {fileID: 0}
- m_RenderMode: 0
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_Lightmapping: 4
- m_LightShadowCasterMode: 0
- m_AreaSize: {x: 1, y: 1}
- m_BounceIntensity: 1
- m_ColorTemperature: 6570
- m_UseColorTemperature: 0
- m_ShadowRadius: 0
- m_ShadowAngle: 0
---- !u!4 &1405375880
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1405375878}
- m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
- m_LocalPosition: {x: 0, y: 1, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
---- !u!1 &1461518024
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1461518032}
- - component: {fileID: 1461518031}
- - component: {fileID: 1461518030}
- - component: {fileID: 1461518029}
- - component: {fileID: 1461518028}
- - component: {fileID: 1461518027}
- - component: {fileID: 1461518026}
- - component: {fileID: 1461518025}
- m_Layer: 0
- m_Name: Quad
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!65 &1461518025
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1461518024}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Size: {x: 1, y: 0.01, z: 3}
- m_Center: {x: 0, y: -0.5, z: -1.5}
---- !u!65 &1461518026
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1461518024}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Size: {x: 1, y: 0.01, z: 3}
- m_Center: {x: 0, y: 0.5, z: -1.5}
---- !u!65 &1461518027
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1461518024}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Size: {x: 0.01, y: 1, z: 3}
- m_Center: {x: 0.5, y: 0, z: -1.5}
---- !u!65 &1461518028
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1461518024}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Size: {x: 0.01, y: 1, z: 3}
- m_Center: {x: -0.5, y: 0, z: -1.5}
---- !u!64 &1461518029
-MeshCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1461518024}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 3
- m_Convex: 0
- m_CookingOptions: 14
- m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &1461518030
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1461518024}
- m_Enabled: 1
- m_CastShadows: 0
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 6eb3f3ba66756364d8b94e662e7e8af5, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &1461518031
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1461518024}
- m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
---- !u!4 &1461518032
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1461518024}
- m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 50, y: 50, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
---- !u!1 &1462312433
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1462312434}
- - component: {fileID: 1462312437}
- - component: {fileID: 1462312436}
- - component: {fileID: 1462312435}
- m_Layer: 0
- m_Name: Pillar
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &1462312434
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1462312433}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 8, y: 3, z: 8}
- m_LocalScale: {x: 1, y: 3, z: 1}
- m_Children: []
- m_Father: {fileID: 1608696205}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!136 &1462312435
-CapsuleCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1462312433}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- m_Radius: 0.5000001
- m_Height: 2
- m_Direction: 1
- m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697}
---- !u!23 &1462312436
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1462312433}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: aef230244d219314fb8453f0365b8176, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &1462312437
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1462312433}
- m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1 &1608696204
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1608696205}
- m_Layer: 0
- m_Name: Shelter
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &1608696205
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1608696204}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 1047741291}
- - {fileID: 612284968}
- - {fileID: 1462312434}
- - {fileID: 856402104}
- - {fileID: 794922165}
- m_Father: {fileID: 0}
- m_RootOrder: 5
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1630383476
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1630383479}
- - component: {fileID: 1630383478}
- - component: {fileID: 1630383477}
- m_Layer: 0
- m_Name: ZoneVisualizer
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!23 &1630383477
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1630383476}
- m_Enabled: 1
- m_CastShadows: 0
- m_ReceiveShadows: 0
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 0
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: a7c679cf124f7ae46a0291ea35848554, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &1630383478
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1630383476}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!4 &1630383479
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1630383476}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 30, y: 30, z: 30}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 7
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1661834277
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1661834279}
- - component: {fileID: 1661834281}
- - component: {fileID: 1661834278}
- - component: {fileID: 1661834280}
- m_Layer: 0
- m_Name: Network
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!114 &1661834278
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1661834277}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 34d1daf9e7dbcb64aa647cb332054ea6, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- dontDestroyOnLoad: 0
- runInBackground: 1
- startOnHeadless: 1
- serverTickRate: 30
- showDebugMessages: 0
- offlineScene:
- onlineScene:
- transport: {fileID: 1661834280}
- networkAddress: localhost
- maxConnections: 4
- authenticator: {fileID: 0}
- playerPrefab: {fileID: 8872462076811691049, guid: a5bdca0a2315d43499be7dcef473fbc7,
- type: 3}
- autoCreatePlayer: 1
- playerSpawnMethod: 1
- spawnPrefabs:
- - {fileID: 1076878374699499732, guid: e1971f4a8c7661546bc509b44bd91b80, type: 3}
- - {fileID: 5623359707189648430, guid: 4ff300cf6bb3c6342a9552c4f18788c8, type: 3}
- - {fileID: 6852530814182375312, guid: 12a4c14e672c00b4b840f937d824b890, type: 3}
- - {fileID: 855244094988030905, guid: f6d08eb9a8e35d84fa30a7e3ae64181a, type: 3}
- - {fileID: 160176457, guid: ab222ed73ada1ac4ba2f61e843d7627c, type: 3}
- subScenes:
- - SubScene
---- !u!4 &1661834279
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1661834277}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &1661834280
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1661834277}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- OnClientConnected:
- m_PersistentCalls:
- m_Calls: []
- OnClientDataReceived:
- m_PersistentCalls:
- m_Calls: []
- OnClientError:
- m_PersistentCalls:
- m_Calls: []
- OnClientDisconnected:
- m_PersistentCalls:
- m_Calls: []
- OnServerConnected:
- m_PersistentCalls:
- m_Calls: []
- OnServerDataReceived:
- m_PersistentCalls:
- m_Calls: []
- OnServerError:
- m_PersistentCalls:
- m_Calls: []
- OnServerDisconnected:
- m_PersistentCalls:
- m_Calls: []
- port: 7777
- NoDelay: 1
- serverMaxMessageSize: 16384
- clientMaxMessageSize: 16384
---- !u!114 &1661834281
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1661834277}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 6442dc8070ceb41f094e44de0bf87274, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- showGUI: 1
- offsetX: 0
- offsetY: 0
---- !u!1 &1727677796
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1727677799}
- - component: {fileID: 1727677798}
- - component: {fileID: 1727677797}
- m_Layer: 0
- m_Name: VisibleRangeSphere
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!23 &1727677797
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1727677796}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: a7c679cf124f7ae46a0291ea35848554, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &1727677798
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1727677796}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!4 &1727677799
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1727677796}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -20, y: 1, z: 20}
- m_LocalScale: {x: 10, y: 10, z: 10}
- m_Children: []
- m_Father: {fileID: 47225731}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1816951099
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1816951100}
- - component: {fileID: 1816951101}
- m_Layer: 0
- m_Name: StartPos
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &1816951100
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1816951099}
- m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068}
- m_LocalPosition: {x: -20, y: 1.08, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1172568542}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0}
---- !u!114 &1816951101
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1816951099}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1001 &1076878375580925077
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- m_TransformParent: {fileID: 909502395}
- m_Modifications:
- - target: {fileID: 1076878374699499732, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_Name
- value: Capsule
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499732, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_StaticEditorFlags
- value: 4294967295
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalPosition.x
- value: 20
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalPosition.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalPosition.z
- value: -20
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalRotation.y
- value: 0.3826836
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalRotation.z
- value: -0
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalRotation.w
- value: -0.92387944
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_RootOrder
- value: 3
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 315
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 2648107611936813301, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_SceneId
- value: 2061538488
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: e1971f4a8c7661546bc509b44bd91b80, type: 3}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/MainScene.unity.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/MainScene.unity.meta
deleted file mode 100644
index a231750..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/MainScene.unity.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 7a0eee2f518e9dc4fb628d96dc452faf
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/SubScene.unity b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/SubScene.unity
deleted file mode 100644
index a1b2bf5..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/SubScene.unity
+++ /dev/null
@@ -1,798 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!29 &1
-OcclusionCullingSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_OcclusionBakeSettings:
- smallestOccluder: 5
- smallestHole: 0.25
- backfaceThreshold: 100
- m_SceneGUID: 00000000000000000000000000000000
- m_OcclusionCullingData: {fileID: 0}
---- !u!104 &2
-RenderSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 9
- m_Fog: 0
- m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
- m_FogMode: 3
- m_FogDensity: 0.01
- m_LinearFogStart: 0
- m_LinearFogEnd: 300
- m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
- m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
- m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
- m_AmbientIntensity: 1
- m_AmbientMode: 0
- m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
- m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
- m_HaloStrength: 0.5
- m_FlareStrength: 1
- m_FlareFadeSpeed: 3
- m_HaloTexture: {fileID: 0}
- m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
- m_DefaultReflectionMode: 0
- m_DefaultReflectionResolution: 128
- m_ReflectionBounces: 1
- m_ReflectionIntensity: 1
- m_CustomReflection: {fileID: 0}
- m_Sun: {fileID: 0}
- m_IndirectSpecularColor: {r: 0.37311953, g: 0.38074014, b: 0.3587274, a: 1}
- m_UseRadianceAmbientProbe: 0
---- !u!157 &3
-LightmapSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 11
- m_GIWorkflowMode: 0
- m_GISettings:
- serializedVersion: 2
- m_BounceScale: 1
- m_IndirectOutputScale: 1
- m_AlbedoBoost: 1
- m_EnvironmentLightingMode: 0
- m_EnableBakedLightmaps: 0
- m_EnableRealtimeLightmaps: 0
- m_LightmapEditorSettings:
- serializedVersion: 10
- m_Resolution: 2
- m_BakeResolution: 40
- m_AtlasSize: 1024
- m_AO: 0
- m_AOMaxDistance: 1
- m_CompAOExponent: 1
- m_CompAOExponentDirect: 0
- m_Padding: 2
- m_LightmapParameters: {fileID: 0}
- m_LightmapsBakeMode: 1
- m_TextureCompression: 1
- m_FinalGather: 0
- m_FinalGatherFiltering: 1
- m_FinalGatherRayCount: 256
- m_ReflectionCompression: 2
- m_MixedBakeMode: 2
- m_BakeBackend: 1
- m_PVRSampling: 1
- m_PVRDirectSampleCount: 32
- m_PVRSampleCount: 500
- m_PVRBounces: 2
- m_PVRFilterTypeDirect: 0
- m_PVRFilterTypeIndirect: 0
- m_PVRFilterTypeAO: 0
- m_PVRFilteringMode: 1
- m_PVRCulling: 1
- m_PVRFilteringGaussRadiusDirect: 1
- m_PVRFilteringGaussRadiusIndirect: 5
- m_PVRFilteringGaussRadiusAO: 2
- m_PVRFilteringAtrousPositionSigmaDirect: 0.5
- m_PVRFilteringAtrousPositionSigmaIndirect: 2
- m_PVRFilteringAtrousPositionSigmaAO: 1
- m_ShowResolutionOverlay: 1
- m_LightingDataAsset: {fileID: 112000002, guid: b287b2046ddc6af4b9ddc48ab35ca3cb,
- type: 2}
- m_UseShadowmask: 1
---- !u!196 &4
-NavMeshSettings:
- serializedVersion: 2
- m_ObjectHideFlags: 0
- m_BuildSettings:
- serializedVersion: 2
- agentTypeID: 0
- agentRadius: 0.5
- agentHeight: 2
- agentSlope: 45
- agentClimb: 0.4
- ledgeDropHeight: 0
- maxJumpAcrossDistance: 0
- minRegionArea: 2
- manualCellSize: 0
- cellSize: 0.16666667
- manualTileSize: 0
- tileSize: 256
- accuratePlacement: 0
- debug:
- m_Flags: 0
- m_NavMeshData: {fileID: 0}
---- !u!1 &21610633
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 21610634}
- - component: {fileID: 21610636}
- - component: {fileID: 21610635}
- m_Layer: 0
- m_Name: VisibleRange
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &21610634
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 21610633}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 3, y: 1, z: -3}
- m_LocalScale: {x: 10, y: 10, z: 10}
- m_Children: []
- m_Father: {fileID: 1690140971}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!23 &21610635
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 21610633}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: a7c679cf124f7ae46a0291ea35848554, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &21610636
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 21610633}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1001 &174598777
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- m_TransformParent: {fileID: 0}
- m_Modifications:
- - target: {fileID: 1076878374699499732, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_Name
- value: Capsule
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499732, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_StaticEditorFlags
- value: 4294967295
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalPosition.x
- value: 3
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalPosition.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalPosition.z
- value: -3
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalRotation.y
- value: 0.92387956
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalRotation.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalRotation.w
- value: 0.38268343
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_RootOrder
- value: 3
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 135
- objectReference: {fileID: 0}
- - target: {fileID: 1076878374699499735, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 2648107611936813301, guid: e1971f4a8c7661546bc509b44bd91b80,
- type: 3}
- propertyPath: m_SceneId
- value: 15452677
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: e1971f4a8c7661546bc509b44bd91b80, type: 3}
---- !u!1 &222935521
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 222935522}
- - component: {fileID: 222935524}
- - component: {fileID: 222935523}
- m_Layer: 0
- m_Name: VisibleRange
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &222935522
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 222935521}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -3, y: 1, z: 3}
- m_LocalScale: {x: 10, y: 10, z: 10}
- m_Children: []
- m_Father: {fileID: 1690140971}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!23 &222935523
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 222935521}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: a7c679cf124f7ae46a0291ea35848554, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &222935524
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 222935521}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1 &507729669
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 507729670}
- - component: {fileID: 507729672}
- - component: {fileID: 507729671}
- m_Layer: 0
- m_Name: VisibleRange
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &507729670
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 507729669}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 3, y: 1, z: 3}
- m_LocalScale: {x: 10, y: 10, z: 10}
- m_Children: []
- m_Father: {fileID: 1690140971}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!23 &507729671
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 507729669}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: a7c679cf124f7ae46a0291ea35848554, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &507729672
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 507729669}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1 &1690140970
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1690140971}
- m_Layer: 0
- m_Name: ProximityVisualizers
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &1690140971
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1690140970}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 1722279649}
- - {fileID: 222935522}
- - {fileID: 507729670}
- - {fileID: 21610634}
- m_Father: {fileID: 0}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1722279648
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1722279649}
- - component: {fileID: 1722279651}
- - component: {fileID: 1722279650}
- m_Layer: 0
- m_Name: VisibleRange
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &1722279649
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1722279648}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -3, y: 1, z: -3}
- m_LocalScale: {x: 10, y: 10, z: 10}
- m_Children: []
- m_Father: {fileID: 1690140971}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!23 &1722279650
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1722279648}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: a7c679cf124f7ae46a0291ea35848554, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!33 &1722279651
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1722279648}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!1001 &855244095324068329
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- m_TransformParent: {fileID: 0}
- m_Modifications:
- - target: {fileID: 855244094988030905, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_Name
- value: Sphere
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalPosition.x
- value: -3
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalPosition.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalPosition.z
- value: 3
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalRotation.y
- value: 0.3826836
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalRotation.z
- value: -0
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalRotation.w
- value: -0.92387944
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_RootOrder
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 315
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030909, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 855244094988030911, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_SceneId
- value: 11893259
- objectReference: {fileID: 0}
- - target: {fileID: 855244096231524078, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_CastShadows
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 855244096231524078, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_ReceiveShadows
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 855244096231524078, guid: f6d08eb9a8e35d84fa30a7e3ae64181a,
- type: 3}
- propertyPath: m_ReflectionProbeUsage
- value: 0
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: f6d08eb9a8e35d84fa30a7e3ae64181a, type: 3}
---- !u!1001 &5623359707641229621
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- m_TransformParent: {fileID: 0}
- m_Modifications:
- - target: {fileID: 5623359707189648430, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_Name
- value: Cube
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648430, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_Icon
- value:
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_LocalPosition.x
- value: -3
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_LocalPosition.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_LocalPosition.z
- value: -3
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_LocalRotation.y
- value: 0.9238796
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_LocalRotation.z
- value: -0
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_LocalRotation.w
- value: -0.38268325
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_RootOrder
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 225
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648426, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 5623359707189648404, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_SceneId
- value: 4733130
- objectReference: {fileID: 0}
- - target: {fileID: 5623359706949397433, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_CastShadows
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 5623359706949397433, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_ReceiveShadows
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 5623359706949397433, guid: 4ff300cf6bb3c6342a9552c4f18788c8,
- type: 3}
- propertyPath: m_ReflectionProbeUsage
- value: 0
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: 4ff300cf6bb3c6342a9552c4f18788c8, type: 3}
---- !u!1001 &6852530815080958608
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- m_TransformParent: {fileID: 0}
- m_Modifications:
- - target: {fileID: 6852530814182375312, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_Name
- value: Cylinder
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalPosition.x
- value: 3
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalPosition.y
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalPosition.z
- value: 3
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalRotation.y
- value: 0.38268343
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalRotation.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalRotation.w
- value: 0.92387956
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_RootOrder
- value: 2
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 45
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375316, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375318, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_AssetId
- value: 12a4c14e672c00b4b840f937d824b890
- objectReference: {fileID: 0}
- - target: {fileID: 6852530814182375318, guid: 12a4c14e672c00b4b840f937d824b890,
- type: 3}
- propertyPath: m_SceneId
- value: 4633990
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: 12a4c14e672c00b4b840f937d824b890, type: 3}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/SubScene.unity.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/SubScene.unity.meta
deleted file mode 100644
index 94a2050..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scenes/SubScene.unity.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 7f4fd683fc6d866418c95f99977533a6
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts.meta
deleted file mode 100644
index cb97b32..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: f9c36b0deb5d9b245b7c97e3d6eeed29
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/AdditiveNetworkManager.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/AdditiveNetworkManager.cs
deleted file mode 100644
index 14f061d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/AdditiveNetworkManager.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using UnityEngine;
-using System.Collections;
-using UnityEngine.SceneManagement;
-
-namespace Mirror.Examples.Additive
-{
- public class AdditiveNetworkManager : NetworkManager
- {
- [Scene]
- [Tooltip("Add all sub-scenes to this list")]
- public string[] subScenes;
-
- public override void OnStartServer()
- {
- base.OnStartServer();
- Debug.Log("Loading Scenes");
-
- // load all subscenes on the server only
- foreach (string sceneName in subScenes)
- {
- SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
- Debug.LogFormat("Loaded {0}", sceneName);
- }
- }
-
- public override void OnStopServer()
- {
- Debug.Log("Stopping Server");
- base.OnStopServer();
- UnloadScenes();
- }
-
- public override void OnStopClient()
- {
- Debug.Log("Stopping Client");
- base.OnStopClient();
- UnloadScenes();
- }
-
- void UnloadScenes()
- {
- Debug.Log("Unloading Scenes");
- foreach (string sceneName in subScenes)
- if (SceneManager.GetSceneByName(sceneName).IsValid())
- StartCoroutine(UnloadScene(sceneName));
- }
-
- IEnumerator UnloadScene(string sceneName)
- {
- yield return SceneManager.UnloadSceneAsync(sceneName);
- yield return Resources.UnloadUnusedAssets();
- Debug.LogFormat("Unloaded {0}", sceneName);
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/AdditiveNetworkManager.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/AdditiveNetworkManager.cs.meta
deleted file mode 100644
index 0df3fb3..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/AdditiveNetworkManager.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 34d1daf9e7dbcb64aa647cb332054ea6
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/PlayerController.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/PlayerController.cs
deleted file mode 100644
index 741bfe8..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/PlayerController.cs
+++ /dev/null
@@ -1,120 +0,0 @@
-using UnityEngine;
-
-namespace Mirror.Examples.Additive
-{
- [RequireComponent(typeof(CharacterController))]
- public class PlayerController : NetworkBehaviour
- {
- public override void OnStartServer()
- {
- base.OnStartServer();
- playerColor = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);
- }
-
- [SyncVar(hook = nameof(SetColor))]
- Color playerColor = Color.black;
-
- // Unity clones the material when GetComponent().material is called
- // Cache it here and destroy it in OnDestroy to prevent a memory leak
- Material cachedMaterial;
-
- void SetColor(Color color)
- {
- if (cachedMaterial == null) cachedMaterial = GetComponent().material;
- cachedMaterial.color = color;
- }
-
- void OnDisable()
- {
- if (isLocalPlayer)
- {
- Camera.main.transform.SetParent(null);
- Camera.main.transform.localPosition = new Vector3(0f, 50f, 0f);
- Camera.main.transform.localEulerAngles = new Vector3(90f, 0f, 0f);
- }
- }
-
- void OnDestroy()
- {
- Destroy(cachedMaterial);
- }
-
- CharacterController characterController;
-
- public override void OnStartLocalPlayer()
- {
- base.OnStartLocalPlayer();
-
- characterController = GetComponent();
-
- Camera.main.transform.SetParent(transform);
- Camera.main.transform.localPosition = new Vector3(0f, 3f, -8f);
- Camera.main.transform.localEulerAngles = new Vector3(10f, 0f, 0f);
- }
-
- [Header("Movement Settings")]
- public float moveSpeed = 8f;
- public float turnSpeedAccel = 5f;
- public float turnSpeedDecel = 5f;
- public float maxTurnSpeed = 150f;
-
- [Header("Jump Settings")]
- public float jumpSpeed = 0f;
- public float jumpFactor = .025F;
-
- [Header("Diagnostics")]
- public float horizontal = 0f;
- public float vertical = 0f;
- public float turn = 0f;
- public bool isGrounded = true;
- public bool isFalling = false;
-
- void Update()
- {
- if (!isLocalPlayer) return;
-
- horizontal = Input.GetAxis("Horizontal");
- vertical = Input.GetAxis("Vertical");
-
- if (Input.GetKey(KeyCode.Q) && (turn > -maxTurnSpeed))
- turn -= turnSpeedAccel;
- else if (Input.GetKey(KeyCode.E) && (turn < maxTurnSpeed))
- turn += turnSpeedAccel;
- else if (turn > turnSpeedDecel)
- turn -= turnSpeedDecel;
- else if (turn < -turnSpeedDecel)
- turn += turnSpeedDecel;
- else
- turn = 0f;
-
- if (!isFalling && Input.GetKey(KeyCode.Space) && (isGrounded || jumpSpeed < 1))
- jumpSpeed += jumpFactor;
- else if (isGrounded)
- isFalling = false;
- else
- {
- isFalling = true;
- jumpSpeed = 0;
- }
- }
-
- void FixedUpdate()
- {
- if (!isLocalPlayer || characterController == null) return;
-
- transform.Rotate(0f, turn * Time.fixedDeltaTime, 0f);
-
- Vector3 direction = new Vector3(horizontal, jumpSpeed, vertical);
- direction = Vector3.ClampMagnitude(direction, 1f);
- direction = transform.TransformDirection(direction);
- direction *= moveSpeed;
-
- if (jumpSpeed > 0)
- characterController.Move(direction * Time.fixedDeltaTime);
- else
- characterController.SimpleMove(direction);
-
- isGrounded = characterController.isGrounded;
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/PlayerController.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/PlayerController.cs.meta
deleted file mode 100644
index 5deced6..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/PlayerController.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: e8f68561248aaca4fb96847ce24742ee
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ShootingTankBehaviour.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ShootingTankBehaviour.cs
deleted file mode 100644
index 155d7ce..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ShootingTankBehaviour.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using UnityEngine;
-
-namespace Mirror.Examples.Additive
-{
- // This script demonstrates the NetworkAnimator and how to leverage
- // the built-in observers system to track players.
- // Note that all ProximityCheckers should be restricted to the Player layer.
- public class ShootingTankBehaviour : NetworkBehaviour
- {
- [SyncVar]
- public Quaternion rotation;
-
- NetworkAnimator networkAnimator;
-
- [ServerCallback]
- void Start()
- {
- networkAnimator = GetComponent();
- }
-
- [Range(0, 1)]
- public float turnSpeed = 0.1f;
-
- void Update()
- {
- if (isServer && netIdentity.observers.Count > 0)
- ShootNearestPlayer();
-
- if (isClient)
- transform.rotation = Quaternion.Slerp(transform.rotation, rotation, turnSpeed);
- }
-
- [Server]
- void ShootNearestPlayer()
- {
- GameObject target = null;
- float distance = 100f;
-
- foreach (NetworkConnection networkConnection in netIdentity.observers.Values)
- {
- GameObject tempTarget = networkConnection.identity.gameObject;
- float tempDistance = Vector3.Distance(tempTarget.transform.position, transform.position);
-
- if (target == null || distance > tempDistance)
- {
- target = tempTarget;
- distance = tempDistance;
- }
- }
-
- if (target != null)
- {
- transform.LookAt(target.transform.position + Vector3.down);
- rotation = transform.rotation;
- networkAnimator.SetTrigger("Fire");
- }
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ShootingTankBehaviour.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ShootingTankBehaviour.cs.meta
deleted file mode 100644
index 90771ab..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ShootingTankBehaviour.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 7a25c54cd35eb284eb6b8ed19cf60443
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ZoneHandler.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ZoneHandler.cs
deleted file mode 100644
index b4b0118..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ZoneHandler.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using UnityEngine;
-
-namespace Mirror.Examples.Additive
-{
- // This script is attached to a scene object called Zone that is on the Player layer and has:
- // - Sphere Collider with isTrigger = true
- // - Network Identity with Server Only checked
- // These OnTrigger events only run on the server and will only send a message to the player
- // that entered the Zone to load the subscene assigned to the subscene property.
- public class ZoneHandler : NetworkBehaviour
- {
- [Scene]
- [Tooltip("Assign the sub-scene to load for this zone")]
- public string subScene;
-
- [Server]
- void OnTriggerEnter(Collider other)
- {
- Debug.LogFormat("Loading {0}", subScene);
-
- NetworkIdentity networkIdentity = other.gameObject.GetComponent();
- NetworkServer.SendToClientOfPlayer(networkIdentity, new SceneMessage { sceneName = subScene, sceneOperation = SceneOperation.LoadAdditive });
- }
-
- [Server]
- void OnTriggerExit(Collider other)
- {
- Debug.LogFormat("Unloading {0}", subScene);
-
- NetworkIdentity networkIdentity = other.gameObject.GetComponent();
- NetworkServer.SendToClientOfPlayer(networkIdentity, new SceneMessage { sceneName = subScene, sceneOperation = SceneOperation.UnloadAdditive });
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ZoneHandler.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ZoneHandler.cs.meta
deleted file mode 100644
index 126d072..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/AdditiveScenes/Scripts/ZoneHandler.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 884ed76587eb5854abe6b428b791fdcd
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic.meta
deleted file mode 100644
index 653ea78..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 0ea49fcefbc864e19a94091a170fc06c
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Prefabs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Prefabs.meta
deleted file mode 100644
index 234c22a..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Prefabs.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 4f821a97809492a479cac0843442e245
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Prefabs/Player.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Prefabs/Player.prefab
deleted file mode 100644
index 5518f4d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Prefabs/Player.prefab
+++ /dev/null
@@ -1,266 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &1088833922664441133
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1088833922664441134}
- - component: {fileID: 1088833922664441128}
- - component: {fileID: 1088833922664441135}
- m_Layer: 5
- m_Name: PlayerNameText
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1088833922664441134
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833922664441133}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1088833923132447023}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 60, y: -15}
- m_SizeDelta: {x: 120, y: 30}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &1088833922664441128
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833922664441133}
- m_CullTransparentMesh: 0
---- !u!114 &1088833922664441135
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833922664441133}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 0
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 22
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 2
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 1
- m_VerticalOverflow: 1
- m_LineSpacing: 1
- m_Text: Player 00
---- !u!1 &1088833923132447022
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1088833923132447023}
- - component: {fileID: 1088833923132446996}
- - component: {fileID: 1088833923132447019}
- - component: {fileID: 1088833923132447017}
- - component: {fileID: 1088833923132447018}
- m_Layer: 5
- m_Name: Player
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1088833923132447023
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833923132447022}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 1088833922664441134}
- - {fileID: 1088833924003616757}
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 120, y: 60}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &1088833923132446996
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833923132447022}
- m_CullTransparentMesh: 0
---- !u!114 &1088833923132447019
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833923132447022}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0, g: 0, b: 0, a: 0}
- m_RaycastTarget: 0
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!114 &1088833923132447017
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833923132447022}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: a472ac3ae1701d149861871cf416a46d, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- rectTransform: {fileID: 1088833923132447023}
- image: {fileID: 1088833923132447019}
- playerNameText: {fileID: 1088833922664441135}
- playerDataText: {fileID: 1088833924003616759}
---- !u!114 &1088833923132447018
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833923132447022}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 0
- m_AssetId: 22f1fa3a0aff72b46a371f667bb4fb30
- m_SceneId: 0
---- !u!1 &1088833924003616756
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1088833924003616757}
- - component: {fileID: 1088833924003616752}
- - component: {fileID: 1088833924003616759}
- m_Layer: 5
- m_Name: PlayerDataText
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1088833924003616757
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833924003616756}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1088833923132447023}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 60, y: -45}
- m_SizeDelta: {x: 120, y: 30}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &1088833924003616752
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833924003616756}
- m_CullTransparentMesh: 0
---- !u!114 &1088833924003616759
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1088833924003616756}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 0
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 22
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 2
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 1
- m_VerticalOverflow: 1
- m_LineSpacing: 1
- m_Text: 'Data: 000'
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Prefabs/Player.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Prefabs/Player.prefab.meta
deleted file mode 100644
index c6a8284..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Prefabs/Player.prefab.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 22f1fa3a0aff72b46a371f667bb4fb30
-PrefabImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/README.md b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/README.md
deleted file mode 100644
index 3bde055..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Basic Example
-
-This is a bare bones example of a running game with Network Manager and UI prefab players:
-
-1. Remove all scenes from Build Settings, then add the Example scene alone.
-
-2. Open the Example scene and build the project.
-
-3. In the editor, click Play, and LAN Host or LAN Server...it will be listening on port 7777.
- - If you clicked LAN Host, the host player will appear as Player 00.
-
-4. Run one or more instances (up to 16 total players) of the built application.
-
-5. Click LAN Client on each instance.
-
-6. Now you will see all players in the editor and the clients, all with data being updated and synchronized.
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scenes.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scenes.meta
deleted file mode 100644
index 0c751c6..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scenes.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 16f46473489d3364badc2f37c4db8634
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scenes/Example.unity b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scenes/Example.unity
deleted file mode 100644
index da694df..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scenes/Example.unity
+++ /dev/null
@@ -1,618 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!29 &1
-OcclusionCullingSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_OcclusionBakeSettings:
- smallestOccluder: 5
- smallestHole: 0.25
- backfaceThreshold: 100
- m_SceneGUID: 00000000000000000000000000000000
- m_OcclusionCullingData: {fileID: 0}
---- !u!104 &2
-RenderSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 9
- m_Fog: 0
- m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
- m_FogMode: 3
- m_FogDensity: 0.01
- m_LinearFogStart: 0
- m_LinearFogEnd: 300
- m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
- m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
- m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
- m_AmbientIntensity: 1
- m_AmbientMode: 0
- m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
- m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
- m_HaloStrength: 0.5
- m_FlareStrength: 1
- m_FlareFadeSpeed: 3
- m_HaloTexture: {fileID: 0}
- m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
- m_DefaultReflectionMode: 0
- m_DefaultReflectionResolution: 128
- m_ReflectionBounces: 1
- m_ReflectionIntensity: 1
- m_CustomReflection: {fileID: 0}
- m_Sun: {fileID: 0}
- m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
- m_UseRadianceAmbientProbe: 0
---- !u!157 &3
-LightmapSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 11
- m_GIWorkflowMode: 0
- m_GISettings:
- serializedVersion: 2
- m_BounceScale: 1
- m_IndirectOutputScale: 1
- m_AlbedoBoost: 1
- m_EnvironmentLightingMode: 0
- m_EnableBakedLightmaps: 0
- m_EnableRealtimeLightmaps: 0
- m_LightmapEditorSettings:
- serializedVersion: 10
- m_Resolution: 2
- m_BakeResolution: 40
- m_AtlasSize: 1024
- m_AO: 0
- m_AOMaxDistance: 1
- m_CompAOExponent: 1
- m_CompAOExponentDirect: 0
- m_Padding: 2
- m_LightmapParameters: {fileID: 0}
- m_LightmapsBakeMode: 1
- m_TextureCompression: 1
- m_FinalGather: 0
- m_FinalGatherFiltering: 1
- m_FinalGatherRayCount: 256
- m_ReflectionCompression: 2
- m_MixedBakeMode: 2
- m_BakeBackend: 1
- m_PVRSampling: 1
- m_PVRDirectSampleCount: 32
- m_PVRSampleCount: 500
- m_PVRBounces: 2
- m_PVRFilterTypeDirect: 0
- m_PVRFilterTypeIndirect: 0
- m_PVRFilterTypeAO: 0
- m_PVRFilteringMode: 1
- m_PVRCulling: 1
- m_PVRFilteringGaussRadiusDirect: 1
- m_PVRFilteringGaussRadiusIndirect: 5
- m_PVRFilteringGaussRadiusAO: 2
- m_PVRFilteringAtrousPositionSigmaDirect: 0.5
- m_PVRFilteringAtrousPositionSigmaIndirect: 2
- m_PVRFilteringAtrousPositionSigmaAO: 1
- m_ShowResolutionOverlay: 1
- m_LightingDataAsset: {fileID: 0}
- m_UseShadowmask: 1
---- !u!196 &4
-NavMeshSettings:
- serializedVersion: 2
- m_ObjectHideFlags: 0
- m_BuildSettings:
- serializedVersion: 2
- agentTypeID: 0
- agentRadius: 0.5
- agentHeight: 2
- agentSlope: 45
- agentClimb: 0.4
- ledgeDropHeight: 0
- maxJumpAcrossDistance: 0
- minRegionArea: 2
- manualCellSize: 0
- cellSize: 0.16666667
- manualTileSize: 0
- tileSize: 256
- accuratePlacement: 0
- debug:
- m_Flags: 0
- m_NavMeshData: {fileID: 0}
---- !u!1 &249891953
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 249891957}
- - component: {fileID: 249891954}
- - component: {fileID: 249891956}
- - component: {fileID: 249891955}
- m_Layer: 0
- m_Name: NetworkManager
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!114 &249891954
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 249891953}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 6442dc8070ceb41f094e44de0bf87274, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- showGUI: 1
- offsetX: 0
- offsetY: 0
---- !u!114 &249891955
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 249891953}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- OnClientConnected:
- m_PersistentCalls:
- m_Calls: []
- OnClientDataReceived:
- m_PersistentCalls:
- m_Calls: []
- OnClientError:
- m_PersistentCalls:
- m_Calls: []
- OnClientDisconnected:
- m_PersistentCalls:
- m_Calls: []
- OnServerConnected:
- m_PersistentCalls:
- m_Calls: []
- OnServerDataReceived:
- m_PersistentCalls:
- m_Calls: []
- OnServerError:
- m_PersistentCalls:
- m_Calls: []
- OnServerDisconnected:
- m_PersistentCalls:
- m_Calls: []
- port: 7777
- NoDelay: 1
- serverMaxMessageSize: 16384
- clientMaxMessageSize: 16384
---- !u!114 &249891956
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 249891953}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 8aab4c8111b7c411b9b92cf3dbc5bd4e, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- dontDestroyOnLoad: 0
- runInBackground: 1
- startOnHeadless: 0
- serverTickRate: 30
- showDebugMessages: 0
- offlineScene:
- onlineScene:
- transport: {fileID: 249891955}
- networkAddress: localhost
- maxConnections: 16
- authenticator: {fileID: 0}
- playerPrefab: {fileID: 1088833923132447022, guid: 22f1fa3a0aff72b46a371f667bb4fb30,
- type: 3}
- autoCreatePlayer: 1
- playerSpawnMethod: 1
- spawnPrefabs: []
---- !u!4 &249891957
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 249891953}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: -10, y: 4, z: 5}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &288173824
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 288173827}
- - component: {fileID: 288173826}
- - component: {fileID: 288173825}
- m_Layer: 0
- m_Name: Main Camera
- m_TagString: MainCamera
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!81 &288173825
-AudioListener:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 288173824}
- m_Enabled: 1
---- !u!20 &288173826
-Camera:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 288173824}
- m_Enabled: 1
- serializedVersion: 2
- m_ClearFlags: 2
- m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0}
- m_projectionMatrixMode: 1
- m_SensorSize: {x: 36, y: 24}
- m_LensShift: {x: 0, y: 0}
- m_GateFitMode: 2
- m_FocalLength: 50
- m_NormalizedViewPortRect:
- serializedVersion: 2
- x: 0
- y: 0
- width: 1
- height: 1
- near clip plane: 0.3
- far clip plane: 1000
- field of view: 60
- orthographic: 1
- orthographic size: 5
- m_Depth: -1
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_RenderingPath: -1
- m_TargetTexture: {fileID: 0}
- m_TargetDisplay: 0
- m_TargetEye: 3
- m_HDR: 1
- m_AllowMSAA: 1
- m_AllowDynamicResolution: 0
- m_ForceIntoRT: 0
- m_OcclusionCulling: 1
- m_StereoConvergence: 10
- m_StereoSeparation: 0.022
---- !u!4 &288173827
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 288173824}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1, z: -1}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &379082678
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 379082679}
- - component: {fileID: 379082681}
- - component: {fileID: 379082680}
- m_Layer: 5
- m_Name: PlayersPanel
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &379082679
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 379082678}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 533055204}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 0}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &379082680
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 379082678}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0, g: 0, b: 0, a: 0}
- m_RaycastTarget: 0
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &379082681
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 379082678}
- m_CullTransparentMesh: 0
---- !u!1 &522137823
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 522137826}
- - component: {fileID: 522137825}
- - component: {fileID: 522137824}
- m_Layer: 0
- m_Name: EventSystem
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!114 &522137824
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 522137823}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_HorizontalAxis: Horizontal
- m_VerticalAxis: Vertical
- m_SubmitButton: Submit
- m_CancelButton: Cancel
- m_InputActionsPerSecond: 10
- m_RepeatDelay: 0.5
- m_ForceModuleActive: 0
---- !u!114 &522137825
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 522137823}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_FirstSelected: {fileID: 0}
- m_sendNavigationEvents: 1
- m_DragThreshold: 10
---- !u!4 &522137826
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 522137823}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &533055200
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 533055204}
- - component: {fileID: 533055203}
- - component: {fileID: 533055202}
- - component: {fileID: 533055201}
- m_Layer: 5
- m_Name: Canvas
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!114 &533055201
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 533055200}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_IgnoreReversedGraphics: 1
- m_BlockingObjects: 0
- m_BlockingMask:
- serializedVersion: 2
- m_Bits: 4294967295
---- !u!114 &533055202
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 533055200}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_UiScaleMode: 0
- m_ReferencePixelsPerUnit: 100
- m_ScaleFactor: 1
- m_ReferenceResolution: {x: 800, y: 600}
- m_ScreenMatchMode: 0
- m_MatchWidthOrHeight: 0
- m_PhysicalUnit: 3
- m_FallbackScreenDPI: 96
- m_DefaultSpriteDPI: 96
- m_DynamicPixelsPerUnit: 1
---- !u!223 &533055203
-Canvas:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 533055200}
- m_Enabled: 1
- serializedVersion: 3
- m_RenderMode: 0
- m_Camera: {fileID: 0}
- m_PlaneDistance: 100
- m_PixelPerfect: 0
- m_ReceivesEvents: 1
- m_OverrideSorting: 0
- m_OverridePixelPerfect: 0
- m_SortingBucketNormalizedSize: 0
- m_AdditionalShaderChannelsFlag: 0
- m_SortingLayerID: 0
- m_SortingOrder: 0
- m_TargetDisplay: 0
---- !u!224 &533055204
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 533055200}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 0, y: 0, z: 0}
- m_Children:
- - {fileID: 379082679}
- m_Father: {fileID: 0}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 0, y: 0}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 0}
- m_Pivot: {x: 0, y: 0}
---- !u!1 &707756284
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 707756286}
- - component: {fileID: 707756285}
- m_Layer: 0
- m_Name: Directional Light
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!108 &707756285
-Light:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 707756284}
- m_Enabled: 1
- serializedVersion: 8
- m_Type: 1
- m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
- m_Intensity: 1
- m_Range: 10
- m_SpotAngle: 30
- m_CookieSize: 10
- m_Shadows:
- m_Type: 2
- m_Resolution: -1
- m_CustomResolution: -1
- m_Strength: 1
- m_Bias: 0.05
- m_NormalBias: 0.4
- m_NearPlane: 0.2
- m_Cookie: {fileID: 0}
- m_DrawHalo: 0
- m_Flare: {fileID: 0}
- m_RenderMode: 0
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_Lightmapping: 4
- m_LightShadowCasterMode: 0
- m_AreaSize: {x: 1, y: 1}
- m_BounceIntensity: 1
- m_ColorTemperature: 6570
- m_UseColorTemperature: 0
- m_ShadowRadius: 0
- m_ShadowAngle: 0
---- !u!4 &707756286
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 707756284}
- m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
- m_LocalPosition: {x: 0, y: 3, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scenes/Example.unity.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scenes/Example.unity.meta
deleted file mode 100644
index 25c602e..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scenes/Example.unity.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: b30904751905d3f4dacde62ac85ec7c2
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scripts.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scripts.meta
deleted file mode 100644
index 5cc0800..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scripts.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 9c5291659f25af9409bbc25a2d37d628
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scripts/Player.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scripts/Player.cs
deleted file mode 100644
index 1b23ae8..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scripts/Player.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using UnityEngine;
-using UnityEngine.UI;
-
-namespace Mirror.Examples.Basic
-{
- public class Player : NetworkBehaviour
- {
- [Header("Player Components")]
- public RectTransform rectTransform;
- public Image image;
-
- [Header("Child Text Objects")]
- public Text playerNameText;
- public Text playerDataText;
-
- // These are set in OnStartServer and used in OnStartClient
- [SyncVar]
- int playerNo;
- [SyncVar]
- Color playerColor;
-
- // This is updated by UpdateData which is called from OnStartServer via InvokeRepeating
- [SyncVar(hook = nameof(OnPlayerDataChanged))]
- int playerData;
-
- // This is called by the hook of playerData SyncVar above
- void OnPlayerDataChanged(int newPlayerData)
- {
- // Show the data in the UI
- playerDataText.text = string.Format("Data: {0:000}", newPlayerData);
- }
-
- // This fires on server when this player object is network-ready
- public override void OnStartServer()
- {
- base.OnStartServer();
-
- // Set SyncVar values
- playerNo = connectionToClient.connectionId;
- playerColor = Random.ColorHSV(0f, 1f, 0.9f, 0.9f, 1f, 1f);
-
- // Start generating updates
- InvokeRepeating(nameof(UpdateData), 1, 1);
- }
-
- // This only runs on the server, called from OnStartServer via InvokeRepeating
- [ServerCallback]
- void UpdateData()
- {
- playerData = Random.Range(100, 1000);
- }
-
- // This fires on all clients when this player object is network-ready
- public override void OnStartClient()
- {
- base.OnStartClient();
-
- // Make this a child of the layout panel in the Canvas
- transform.SetParent(GameObject.Find("PlayersPanel").transform);
-
- // Calculate position in the layout panel
- int x = 100 + ((playerNo % 4) * 150);
- int y = -170 - ((playerNo / 4) * 80);
- rectTransform.anchoredPosition = new Vector2(x, y);
-
- // Apply SyncVar values
- playerNameText.color = playerColor;
- playerNameText.text = string.Format("Player {0:00}", playerNo);
- }
-
- // This only fires on the local client when this player object is network-ready
- public override void OnStartLocalPlayer()
- {
- base.OnStartLocalPlayer();
-
- // apply a shaded background to our player
- image.color = new Color(1f, 1f, 1f, 0.1f);
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scripts/Player.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scripts/Player.cs.meta
deleted file mode 100644
index cf15827..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Basic/Scripts/Player.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: a472ac3ae1701d149861871cf416a46d
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/ListServer.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/ListServer.cs
deleted file mode 100644
index 58b64d5..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/ListServer.cs
+++ /dev/null
@@ -1,338 +0,0 @@
-// add this component to the NetworkManager
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Text;
-using UnityEngine;
-using UnityEngine.UI;
-
-namespace Mirror.Examples.ListServer
-{
- public class ServerStatus
- {
- public string ip;
- //public ushort port; // <- not all transports use a port. assume default port. feel free to also send a port if needed.
- public string title;
- public ushort players;
- public ushort capacity;
-
- public int lastLatency = -1;
-#if !UNITY_WEBGL // Ping isn't known in WebGL builds
- public Ping ping;
-#endif
- public ServerStatus(string ip, /*ushort port,*/ string title, ushort players, ushort capacity)
- {
- this.ip = ip;
- //this.port = port;
- this.title = title;
- this.players = players;
- this.capacity = capacity;
-#if !UNITY_WEBGL // Ping isn't known in WebGL builds
- ping = new Ping(ip);
-#endif
- }
- }
-
- [RequireComponent(typeof(NetworkManager))]
- public class ListServer : MonoBehaviour
- {
- [Header("Listen Server Connection")]
- public string listServerIp = "127.0.0.1";
- public ushort gameServerToListenPort = 8887;
- public ushort clientToListenPort = 8888;
- public string gameServerTitle = "Deathmatch";
-
- Telepathy.Client gameServerToListenConnection = new Telepathy.Client();
- Telepathy.Client clientToListenConnection = new Telepathy.Client();
-
- [Header("UI")]
- public GameObject mainPanel;
- public Transform content;
- public Text statusText;
- public UIServerStatusSlot slotPrefab;
- public Button serverAndPlayButton;
- public Button serverOnlyButton;
- public GameObject connectingPanel;
- public Text connectingText;
- public Button connectingCancelButton;
- int connectingDots = 0;
-
- // all the servers, stored as dict with unique ip key so we can
- // update them more easily
- // (use "ip:port" if port is needed)
- Dictionary list = new Dictionary();
-
- void Start()
- {
- // examples
- //list["127.0.0.1"] = new ServerStatus("127.0.0.1", "Deathmatch", 3, 10);
- //list["192.168.0.1"] = new ServerStatus("192.168.0.1", "Free for all", 7, 10);
- //list["172.217.22.3"] = new ServerStatus("172.217.22.3", "5vs5", 10, 10);
- //list["172.217.16.142"] = new ServerStatus("172.217.16.142", "Hide & Seek Mod", 0, 10);
-
- // Update once a second. no need to try to reconnect or read data
- // in each Update call
- // -> calling it more than 1/second would also cause significantly
- // more broadcasts in the list server.
- InvokeRepeating(nameof(Tick), 0, 1);
- }
-
- bool IsConnecting() => NetworkClient.active && !ClientScene.ready;
- bool FullyConnected() => NetworkClient.active && ClientScene.ready;
-
- // should we use the client to listen connection?
- bool UseClientToListen()
- {
- return !NetworkManager.isHeadless && !NetworkServer.active && !FullyConnected();
- }
-
- // should we use the game server to listen connection?
- bool UseGameServerToListen()
- {
- return NetworkServer.active;
- }
-
- void Tick()
- {
- TickGameServer();
- TickClient();
- }
-
- // send server status to list server
- void SendStatus()
- {
- BinaryWriter writer = new BinaryWriter(new MemoryStream());
-
- // create message
- writer.Write((ushort)NetworkServer.connections.Count);
- writer.Write((ushort)NetworkManager.singleton.maxConnections);
- byte[] titleBytes = Encoding.UTF8.GetBytes(gameServerTitle);
- writer.Write((ushort)titleBytes.Length);
- writer.Write(titleBytes);
- writer.Flush();
-
- // list server only allows up to 128 bytes per message
- if (writer.BaseStream.Position <= 128)
- {
- // send it
- gameServerToListenConnection.Send(((MemoryStream)writer.BaseStream).ToArray());
- }
- else Debug.LogError("[List Server] List Server will reject messages longer than 128 bytes. Please use a shorter title.");
- }
-
- void TickGameServer()
- {
- // send server data to listen
- if (UseGameServerToListen())
- {
- // connected yet?
- if (gameServerToListenConnection.Connected)
- {
- SendStatus();
- }
- // otherwise try to connect
- // (we may have just started the game)
- else if (!gameServerToListenConnection.Connecting)
- {
- Debug.Log("[List Server] GameServer connecting......");
- gameServerToListenConnection.Connect(listServerIp, gameServerToListenPort);
- }
- }
- // shouldn't use game server, but still using it?
- else if (gameServerToListenConnection.Connected)
- {
- gameServerToListenConnection.Disconnect();
- }
- }
-
- void ParseMessage(byte[] bytes)
- {
- // note: we don't use ReadString here because the list server
- // doesn't know C#'s '7-bit-length + utf8' encoding for strings
- BinaryReader reader = new BinaryReader(new MemoryStream(bytes, false), Encoding.UTF8);
- byte ipBytesLength = reader.ReadByte();
- byte[] ipBytes = reader.ReadBytes(ipBytesLength);
- string ip = new IPAddress(ipBytes).ToString();
- //ushort port = reader.ReadUInt16(); <- not all Transports use a port. assume default.
- ushort players = reader.ReadUInt16();
- ushort capacity = reader.ReadUInt16();
- ushort titleLength = reader.ReadUInt16();
- string title = Encoding.UTF8.GetString(reader.ReadBytes(titleLength));
- //Debug.Log("PARSED: ip=" + ip + /*" port=" + port +*/ " players=" + players + " capacity= " + capacity + " title=" + title);
-
- // build key
- string key = ip/* + ":" + port*/;
-
- // find existing or create new one
- if (list.TryGetValue(key, out ServerStatus server))
- {
- // refresh
- server.title = title;
- server.players = players;
- server.capacity = capacity;
- }
- else
- {
- // create
- server = new ServerStatus(ip, /*port,*/ title, players, capacity);
- }
-
- // save
- list[key] = server;
- }
-
- void TickClient()
- {
- // receive client data from listen
- if (UseClientToListen())
- {
- // connected yet?
- if (clientToListenConnection.Connected)
- {
- // receive latest game server info
- while (clientToListenConnection.GetNextMessage(out Telepathy.Message message))
- {
- // connected?
- if (message.eventType == Telepathy.EventType.Connected)
- Debug.Log("[List Server] Client connected!");
- // data message?
- else if (message.eventType == Telepathy.EventType.Data)
- ParseMessage(message.data);
- // disconnected?
- else if (message.eventType == Telepathy.EventType.Connected)
- Debug.Log("[List Server] Client disconnected.");
- }
-
-#if !UNITY_WEBGL // Ping isn't known in WebGL builds
- // ping again if previous ping finished
- foreach (ServerStatus server in list.Values)
- {
- if (server.ping.isDone)
- {
- server.lastLatency = server.ping.time;
- server.ping = new Ping(server.ip);
- }
- }
-#endif
- }
- // otherwise try to connect
- // (we may have just joined the menu/disconnect from game server)
- else if (!clientToListenConnection.Connecting)
- {
- Debug.Log("[List Server] Client connecting...");
- clientToListenConnection.Connect(listServerIp, clientToListenPort);
- }
- }
- // shouldn't use client, but still using it? (e.g. after joining)
- else if (clientToListenConnection.Connected)
- {
- clientToListenConnection.Disconnect();
- list.Clear();
- }
-
- // refresh UI afterwards
- OnUI();
- }
-
- // instantiate/remove enough prefabs to match amount
- public static void BalancePrefabs(GameObject prefab, int amount, Transform parent)
- {
- // instantiate until amount
- for (int i = parent.childCount; i < amount; ++i)
- {
- Instantiate(prefab, parent, false);
- }
-
- // delete everything that's too much
- // (backwards loop because Destroy changes childCount)
- for (int i = parent.childCount-1; i >= amount; --i)
- Destroy(parent.GetChild(i).gameObject);
- }
-
- void OnUI()
- {
- // only show while client not connected and server not started
- if (!NetworkManager.singleton.isNetworkActive || IsConnecting())
- {
- mainPanel.SetActive(true);
-
- // status text
- if (clientToListenConnection.Connecting)
- {
- //statusText.color = Color.yellow;
- statusText.text = "Connecting...";
- }
- else if (clientToListenConnection.Connected)
- {
- //statusText.color = Color.green;
- statusText.text = "Connected!";
- }
- else
- {
- //statusText.color = Color.gray;
- statusText.text = "Disconnected";
- }
-
- // instantiate/destroy enough slots
- BalancePrefabs(slotPrefab.gameObject, list.Count, content);
-
- // refresh all members
- for (int i = 0; i < list.Values.Count; ++i)
- {
- UIServerStatusSlot slot = content.GetChild(i).GetComponent();
- ServerStatus server = list.Values.ToList()[i];
- slot.titleText.text = server.title;
- slot.playersText.text = server.players + "/" + server.capacity;
- slot.latencyText.text = server.lastLatency != -1 ? server.lastLatency.ToString() : "...";
- slot.addressText.text = server.ip;
- slot.joinButton.interactable = !IsConnecting();
- slot.joinButton.gameObject.SetActive(server.players < server.capacity);
- slot.joinButton.onClick.RemoveAllListeners();
- slot.joinButton.onClick.AddListener(() => {
- NetworkManager.singleton.networkAddress = server.ip;
- NetworkManager.singleton.StartClient();
- });
- }
-
- // server buttons
- serverAndPlayButton.interactable = !IsConnecting();
- serverAndPlayButton.onClick.RemoveAllListeners();
- serverAndPlayButton.onClick.AddListener(() => {
- NetworkManager.singleton.StartHost();
- });
-
- serverOnlyButton.interactable = !IsConnecting();
- serverOnlyButton.onClick.RemoveAllListeners();
- serverOnlyButton.onClick.AddListener(() => {
- NetworkManager.singleton.StartServer();
- });
- }
- else mainPanel.SetActive(false);
-
- // show connecting panel while connecting
- if (IsConnecting())
- {
- connectingPanel.SetActive(true);
-
- // . => .. => ... => ....
- connectingDots = ((connectingDots + 1) % 4);
- connectingText.text = "Connecting" + new string('.', connectingDots);
-
- // cancel button
- connectingCancelButton.onClick.RemoveAllListeners();
- connectingCancelButton.onClick.AddListener(NetworkManager.singleton.StopClient);
- }
- else connectingPanel.SetActive(false);
- }
-
- // disconnect everything when pressing Stop in the Editor
- void OnApplicationQuit()
- {
- if (gameServerToListenConnection.Connected)
- gameServerToListenConnection.Disconnect();
- if (clientToListenConnection.Connected)
- clientToListenConnection.Disconnect();
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes.meta
deleted file mode 100644
index e0412be..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 9826d673f42ad4c59b8fc27ae86729e1
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/NavMesh.asset b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/NavMesh.asset
deleted file mode 100644
index 3acffc8..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/NavMesh.asset and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/NavMesh.asset.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/NavMesh.asset.meta
deleted file mode 100644
index a7a9f22..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/NavMesh.asset.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: b7816657e55c04901be36ace7275ad85
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 23800000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/Scene.unity b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/Scene.unity
deleted file mode 100644
index 2752e69..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/Scene.unity
+++ /dev/null
@@ -1,3389 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!29 &1
-OcclusionCullingSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_OcclusionBakeSettings:
- smallestOccluder: 5
- smallestHole: 0.25
- backfaceThreshold: 100
- m_SceneGUID: 00000000000000000000000000000000
- m_OcclusionCullingData: {fileID: 0}
---- !u!104 &2
-RenderSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 9
- m_Fog: 0
- m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
- m_FogMode: 3
- m_FogDensity: 0.01
- m_LinearFogStart: 0
- m_LinearFogEnd: 300
- m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
- m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
- m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
- m_AmbientIntensity: 1
- m_AmbientMode: 3
- m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
- m_SkyboxMaterial: {fileID: 0}
- m_HaloStrength: 0.5
- m_FlareStrength: 1
- m_FlareFadeSpeed: 3
- m_HaloTexture: {fileID: 0}
- m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
- m_DefaultReflectionMode: 0
- m_DefaultReflectionResolution: 128
- m_ReflectionBounces: 1
- m_ReflectionIntensity: 1
- m_CustomReflection: {fileID: 0}
- m_Sun: {fileID: 0}
- m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
- m_UseRadianceAmbientProbe: 0
---- !u!157 &4
-LightmapSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 11
- m_GIWorkflowMode: 0
- m_GISettings:
- serializedVersion: 2
- m_BounceScale: 1
- m_IndirectOutputScale: 1
- m_AlbedoBoost: 1
- m_EnvironmentLightingMode: 0
- m_EnableBakedLightmaps: 0
- m_EnableRealtimeLightmaps: 0
- m_LightmapEditorSettings:
- serializedVersion: 10
- m_Resolution: 2
- m_BakeResolution: 40
- m_AtlasSize: 1024
- m_AO: 0
- m_AOMaxDistance: 1
- m_CompAOExponent: 0
- m_CompAOExponentDirect: 0
- m_Padding: 2
- m_LightmapParameters: {fileID: 0}
- m_LightmapsBakeMode: 1
- m_TextureCompression: 1
- m_FinalGather: 0
- m_FinalGatherFiltering: 1
- m_FinalGatherRayCount: 1024
- m_ReflectionCompression: 2
- m_MixedBakeMode: 1
- m_BakeBackend: 0
- m_PVRSampling: 1
- m_PVRDirectSampleCount: 32
- m_PVRSampleCount: 500
- m_PVRBounces: 2
- m_PVRFilterTypeDirect: 0
- m_PVRFilterTypeIndirect: 0
- m_PVRFilterTypeAO: 0
- m_PVRFilteringMode: 0
- m_PVRCulling: 1
- m_PVRFilteringGaussRadiusDirect: 1
- m_PVRFilteringGaussRadiusIndirect: 5
- m_PVRFilteringGaussRadiusAO: 2
- m_PVRFilteringAtrousPositionSigmaDirect: 0.5
- m_PVRFilteringAtrousPositionSigmaIndirect: 2
- m_PVRFilteringAtrousPositionSigmaAO: 1
- m_ShowResolutionOverlay: 1
- m_LightingDataAsset: {fileID: 0}
- m_UseShadowmask: 0
---- !u!196 &5
-NavMeshSettings:
- serializedVersion: 2
- m_ObjectHideFlags: 0
- m_BuildSettings:
- serializedVersion: 2
- agentTypeID: 0
- agentRadius: 0.5
- agentHeight: 2
- agentSlope: 45
- agentClimb: 0.4
- ledgeDropHeight: 0
- maxJumpAcrossDistance: 0
- minRegionArea: 2
- manualCellSize: 0
- cellSize: 0.16666667
- manualTileSize: 0
- tileSize: 256
- accuratePlacement: 0
- debug:
- m_Flags: 0
- m_NavMeshData: {fileID: 23800000, guid: b7816657e55c04901be36ace7275ad85, type: 2}
---- !u!1 &13922436
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 13922437}
- - component: {fileID: 13922439}
- - component: {fileID: 13922438}
- m_Layer: 5
- m_Name: TextStatus
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &13922437
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 13922436}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1926990971}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: -29}
- m_SizeDelta: {x: 0, y: 18}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &13922438
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 13922436}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 1
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Status
---- !u!222 &13922439
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 13922436}
- m_CullTransparentMesh: 0
---- !u!1 &21701407
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 21701408}
- - component: {fileID: 21701410}
- - component: {fileID: 21701409}
- m_Layer: 5
- m_Name: TextJoinServer
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &21701408
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 21701407}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 776519261}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: -29}
- m_SizeDelta: {x: 0, y: 18}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &21701409
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 21701407}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 1
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Join Server
---- !u!222 &21701410
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 21701407}
- m_CullTransparentMesh: 0
---- !u!1 &88936773
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 88936777}
- - component: {fileID: 88936776}
- - component: {fileID: 88936775}
- - component: {fileID: 88936774}
- m_Layer: 0
- m_Name: Main Camera
- m_TagString: MainCamera
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!81 &88936774
-AudioListener:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 88936773}
- m_Enabled: 1
---- !u!124 &88936775
-Behaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 88936773}
- m_Enabled: 1
---- !u!20 &88936776
-Camera:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 88936773}
- m_Enabled: 1
- serializedVersion: 2
- m_ClearFlags: 1
- m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0}
- m_projectionMatrixMode: 1
- m_SensorSize: {x: 36, y: 24}
- m_LensShift: {x: 0, y: 0}
- m_GateFitMode: 2
- m_FocalLength: 50
- m_NormalizedViewPortRect:
- serializedVersion: 2
- x: 0
- y: 0
- width: 1
- height: 1
- near clip plane: 0.3
- far clip plane: 1000
- field of view: 60
- orthographic: 0
- orthographic size: 5
- m_Depth: -1
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_RenderingPath: -1
- m_TargetTexture: {fileID: 0}
- m_TargetDisplay: 0
- m_TargetEye: 3
- m_HDR: 1
- m_AllowMSAA: 1
- m_AllowDynamicResolution: 0
- m_ForceIntoRT: 0
- m_OcclusionCulling: 1
- m_StereoConvergence: 10
- m_StereoSeparation: 0.022
---- !u!4 &88936777
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 88936773}
- m_LocalRotation: {x: 0, y: 0.92387956, z: -0.38268343, w: 0}
- m_LocalPosition: {x: 0, y: 6.5, z: 8}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 45, y: 180, z: 0}
---- !u!1 &123981370
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 123981371}
- - component: {fileID: 123981373}
- - component: {fileID: 123981372}
- m_Layer: 5
- m_Name: Text
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &123981371
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 123981370}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 276447173}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 0}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &123981372
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 123981370}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Cancel
---- !u!222 &123981373
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 123981370}
- m_CullTransparentMesh: 0
---- !u!1 &177548782
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 177548783}
- - component: {fileID: 177548785}
- - component: {fileID: 177548784}
- m_Layer: 5
- m_Name: TextTitle
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &177548783
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 177548782}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1007872741}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0.5}
- m_AnchorMax: {x: 1, y: 0.5}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: -36, y: 20}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &177548784
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 177548782}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.23137255, g: 1, b: 0.6862745, a: 1}
- m_RaycastTarget: 0
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 14
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Mirror ListServer Demo*
---- !u!222 &177548785
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 177548782}
- m_CullTransparentMesh: 0
---- !u!1 &232720476
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 232720477}
- - component: {fileID: 232720479}
- - component: {fileID: 232720478}
- m_Layer: 5
- m_Name: Text
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &232720477
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 232720476}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1578438653}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 7, y: 0}
- m_SizeDelta: {x: 218, y: 20}
- m_Pivot: {x: 0, y: 1}
---- !u!114 &232720478
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 232720476}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 1
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 3
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Server
---- !u!222 &232720479
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 232720476}
- m_CullTransparentMesh: 0
---- !u!1 &251893064
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 251893065}
- - component: {fileID: 251893066}
- m_Layer: 0
- m_Name: Spawn
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &251893065
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 251893064}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 3, y: 0, z: 3}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 8
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &251893066
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 251893064}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &276447172
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 276447173}
- - component: {fileID: 276447176}
- - component: {fileID: 276447175}
- - component: {fileID: 276447174}
- m_Layer: 5
- m_Name: ButtonCancel
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &276447173
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 276447172}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 123981371}
- m_Father: {fileID: 1926990971}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 0}
- m_AnchoredPosition: {x: 4, y: 16}
- m_SizeDelta: {x: -8, y: 20}
- m_Pivot: {x: 0, y: 0.5}
---- !u!114 &276447174
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 276447172}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Navigation:
- m_Mode: 3
- m_SelectOnUp: {fileID: 0}
- m_SelectOnDown: {fileID: 0}
- m_SelectOnLeft: {fileID: 0}
- m_SelectOnRight: {fileID: 0}
- m_Transition: 1
- m_Colors:
- m_NormalColor: {r: 0.32156864, g: 0.32156864, b: 0.32156864, a: 1}
- m_HighlightedColor: {r: 0.3529412, g: 0.3529412, b: 0.3529412, a: 1}
- m_PressedColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 1}
- m_DisabledColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 0.2509804}
- m_ColorMultiplier: 1
- m_FadeDuration: 0.1
- m_SpriteState:
- m_HighlightedSprite: {fileID: 0}
- m_PressedSprite: {fileID: 0}
- m_DisabledSprite: {fileID: 0}
- m_AnimationTriggers:
- m_NormalTrigger: Normal
- m_HighlightedTrigger: Highlighted
- m_PressedTrigger: Pressed
- m_DisabledTrigger: Disabled
- m_Interactable: 1
- m_TargetGraphic: {fileID: 276447175}
- m_OnClick:
- m_PersistentCalls:
- m_Calls: []
---- !u!114 &276447175
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 276447172}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &276447176
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 276447172}
- m_CullTransparentMesh: 0
---- !u!1 &354490534
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 354490535}
- - component: {fileID: 354490537}
- - component: {fileID: 354490536}
- m_Layer: 5
- m_Name: Text
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &354490535
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 354490534}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1578438653}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 345, y: 0}
- m_SizeDelta: {x: 130, y: 20}
- m_Pivot: {x: 0, y: 1}
---- !u!114 &354490536
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 354490534}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 1
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 5
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Address
---- !u!222 &354490537
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 354490534}
- m_CullTransparentMesh: 0
---- !u!1 &424897549
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 424897550}
- - component: {fileID: 424897552}
- - component: {fileID: 424897551}
- m_Layer: 5
- m_Name: Text
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &424897550
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 424897549}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1578438653}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 225, y: 0}
- m_SizeDelta: {x: 60, y: 20}
- m_Pivot: {x: 0, y: 1}
---- !u!114 &424897551
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 424897549}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 1
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 5
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Players
---- !u!222 &424897552
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 424897549}
- m_CullTransparentMesh: 0
---- !u!1 &531282979
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 531282980}
- - component: {fileID: 531282982}
- - component: {fileID: 531282981}
- m_Layer: 5
- m_Name: Text
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &531282980
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 531282979}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1004751478}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 0}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &531282981
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 531282979}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Server & Play
---- !u!222 &531282982
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 531282979}
- m_CullTransparentMesh: 0
---- !u!1 &535675709
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 535675710}
- - component: {fileID: 535675712}
- - component: {fileID: 535675711}
- m_Layer: 5
- m_Name: Text
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &535675710
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 535675709}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1578438653}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 285, y: 0}
- m_SizeDelta: {x: 60, y: 20}
- m_Pivot: {x: 0, y: 1}
---- !u!114 &535675711
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 535675709}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 1
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 5
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Latency
---- !u!222 &535675712
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 535675709}
- m_CullTransparentMesh: 0
---- !u!1 &535739935
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 535739936}
- - component: {fileID: 535739937}
- m_Layer: 0
- m_Name: Spawn
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &535739936
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 535739935}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 3, y: 0, z: -3}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 6
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &535739937
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 535739935}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &583153858
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 583153859}
- - component: {fileID: 583153861}
- - component: {fileID: 583153860}
- m_Layer: 5
- m_Name: Content
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &583153859
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 583153858}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1918165881}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 560, y: 0}
- m_Pivot: {x: 0, y: 1}
---- !u!114 &583153860
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 583153858}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -2095666955, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Padding:
- m_Left: 2
- m_Right: 2
- m_Top: 4
- m_Bottom: 2
- m_ChildAlignment: 0
- m_StartCorner: 0
- m_StartAxis: 0
- m_CellSize: {x: 560, y: 16}
- m_Spacing: {x: 0, y: 0}
- m_Constraint: 1
- m_ConstraintCount: 1
---- !u!114 &583153861
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 583153858}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_HorizontalFit: 0
- m_VerticalFit: 2
---- !u!1 &586458803
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 586458804}
- - component: {fileID: 586458807}
- - component: {fileID: 586458806}
- - component: {fileID: 586458805}
- m_Layer: 5
- m_Name: Scrollbar Vertical
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &586458804
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 586458803}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 1345848863}
- m_Father: {fileID: 1918165881}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 1, y: 0}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 20, y: 0}
- m_Pivot: {x: 1, y: 1}
---- !u!114 &586458805
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 586458803}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -2061169968, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Navigation:
- m_Mode: 3
- m_SelectOnUp: {fileID: 0}
- m_SelectOnDown: {fileID: 0}
- m_SelectOnLeft: {fileID: 0}
- m_SelectOnRight: {fileID: 0}
- m_Transition: 1
- m_Colors:
- m_NormalColor: {r: 0.4117647, g: 0.4117647, b: 0.4117647, a: 1}
- m_HighlightedColor: {r: 0.41176474, g: 0.41176474, b: 0.41176474, a: 1}
- m_PressedColor: {r: 0.41176474, g: 0.41176474, b: 0.41176474, a: 1}
- m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
- m_ColorMultiplier: 1
- m_FadeDuration: 0.1
- m_SpriteState:
- m_HighlightedSprite: {fileID: 0}
- m_PressedSprite: {fileID: 0}
- m_DisabledSprite: {fileID: 0}
- m_AnimationTriggers:
- m_NormalTrigger: Normal
- m_HighlightedTrigger: Highlighted
- m_PressedTrigger: Pressed
- m_DisabledTrigger: Disabled
- m_Interactable: 1
- m_TargetGraphic: {fileID: 2064208032}
- m_HandleRect: {fileID: 2064208031}
- m_Direction: 2
- m_Value: 0
- m_Size: 1
- m_NumberOfSteps: 0
- m_OnValueChanged:
- m_PersistentCalls:
- m_Calls: []
---- !u!114 &586458806
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 586458803}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.24313726, g: 0.24313726, b: 0.24313726, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &586458807
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 586458803}
- m_CullTransparentMesh: 0
---- !u!1 &635355836
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 635355837}
- - component: {fileID: 635355839}
- - component: {fileID: 635355838}
- m_Layer: 5
- m_Name: Text
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &635355837
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 635355836}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1578438653}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 0, y: 1}
- m_AnchoredPosition: {x: 475, y: 0}
- m_SizeDelta: {x: 40, y: 20}
- m_Pivot: {x: 0, y: 1}
---- !u!114 &635355838
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 635355836}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 1
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 5
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Action
---- !u!222 &635355839
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 635355836}
- m_CullTransparentMesh: 0
---- !u!1 &651109221
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 651109222}
- - component: {fileID: 651109224}
- - component: {fileID: 651109223}
- m_Layer: 5
- m_Name: Background
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &651109222
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 651109221}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1206549608}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 863, y: 754}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &651109223
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 651109221}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.39215687, g: 0.58431375, b: 0.92941177, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 0}
- m_Type: 0
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &651109224
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 651109221}
- m_CullTransparentMesh: 0
---- !u!1 &712827150
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 712827151}
- - component: {fileID: 712827153}
- - component: {fileID: 712827152}
- m_Layer: 5
- m_Name: TextStatus
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &712827151
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 712827150}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 776519261}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 1, y: 1}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: -3, y: -19}
- m_SizeDelta: {x: 157.79, y: 19}
- m_Pivot: {x: 1, y: 1}
---- !u!114 &712827152
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 712827150}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 0.24313726}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 2
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 5
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Status
---- !u!222 &712827153
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 712827150}
- m_CullTransparentMesh: 0
---- !u!1 &719699535
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1206549608}
- m_Layer: 5
- m_Name: ServerList
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!1 &747705678
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 747705679}
- - component: {fileID: 747705681}
- - component: {fileID: 747705680}
- m_Layer: 5
- m_Name: TitleBar
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &747705679
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 747705678}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 1093045669}
- m_Father: {fileID: 1926990971}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 20}
- m_Pivot: {x: 0.5, y: 1}
---- !u!114 &747705680
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 747705678}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.31764707, g: 0.31764707, b: 0.31764707, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &747705681
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 747705678}
- m_CullTransparentMesh: 0
---- !u!1 &776519260
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 776519261}
- - component: {fileID: 776519264}
- - component: {fileID: 776519263}
- m_Layer: 5
- m_Name: ServerListPanel
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &776519261
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 776519260}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 1007872741}
- - {fileID: 21701408}
- - {fileID: 712827151}
- - {fileID: 1578438653}
- - {fileID: 1918165881}
- - {fileID: 1052220088}
- - {fileID: 1291804678}
- - {fileID: 777480155}
- m_Father: {fileID: 1206549608}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0.5, y: 0.5}
- m_AnchorMax: {x: 0.5, y: 0.5}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 526, y: 400}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &776519263
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 776519260}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.19215687, g: 0.19215687, b: 0.19215687, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &776519264
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 776519260}
- m_CullTransparentMesh: 0
---- !u!1 &777480154
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 777480155}
- - component: {fileID: 777480157}
- - component: {fileID: 777480156}
- m_Layer: 5
- m_Name: TextFootnote
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &777480155
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 777480154}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 776519261}
- m_RootOrder: 7
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 0}
- m_AnchoredPosition: {x: 0, y: -10}
- m_SizeDelta: {x: 0, y: 20}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &777480156
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 777480154}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 2
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: '* Host your own List Server with: mirror-networking.com/list-server'
---- !u!222 &777480157
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 777480154}
- m_CullTransparentMesh: 0
---- !u!1 &993261493
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 993261494}
- - component: {fileID: 993261497}
- - component: {fileID: 993261496}
- - component: {fileID: 993261495}
- m_Layer: 5
- m_Name: ButtonServerOnly
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &993261494
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 993261493}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 2020215609}
- m_Father: {fileID: 1291804678}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 1, y: 0.5}
- m_AnchorMax: {x: 1, y: 0.5}
- m_AnchoredPosition: {x: -2, y: 0}
- m_SizeDelta: {x: 260, y: 20}
- m_Pivot: {x: 1, y: 0.5}
---- !u!114 &993261495
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 993261493}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Navigation:
- m_Mode: 3
- m_SelectOnUp: {fileID: 0}
- m_SelectOnDown: {fileID: 0}
- m_SelectOnLeft: {fileID: 0}
- m_SelectOnRight: {fileID: 0}
- m_Transition: 1
- m_Colors:
- m_NormalColor: {r: 0.32156864, g: 0.32156864, b: 0.32156864, a: 1}
- m_HighlightedColor: {r: 0.3529412, g: 0.3529412, b: 0.3529412, a: 1}
- m_PressedColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 1}
- m_DisabledColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 0.2509804}
- m_ColorMultiplier: 1
- m_FadeDuration: 0.1
- m_SpriteState:
- m_HighlightedSprite: {fileID: 0}
- m_PressedSprite: {fileID: 0}
- m_DisabledSprite: {fileID: 0}
- m_AnimationTriggers:
- m_NormalTrigger: Normal
- m_HighlightedTrigger: Highlighted
- m_PressedTrigger: Pressed
- m_DisabledTrigger: Disabled
- m_Interactable: 1
- m_TargetGraphic: {fileID: 993261496}
- m_OnClick:
- m_PersistentCalls:
- m_Calls: []
---- !u!114 &993261496
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 993261493}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &993261497
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 993261493}
- m_CullTransparentMesh: 0
---- !u!1 &1004751477
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1004751478}
- - component: {fileID: 1004751481}
- - component: {fileID: 1004751480}
- - component: {fileID: 1004751479}
- m_Layer: 5
- m_Name: ButtonServer&Play
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1004751478
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1004751477}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 531282980}
- m_Father: {fileID: 1291804678}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0.5}
- m_AnchorMax: {x: 0, y: 0.5}
- m_AnchoredPosition: {x: 2, y: 0}
- m_SizeDelta: {x: 260, y: 20}
- m_Pivot: {x: 0, y: 0.5}
---- !u!114 &1004751479
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1004751477}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Navigation:
- m_Mode: 3
- m_SelectOnUp: {fileID: 0}
- m_SelectOnDown: {fileID: 0}
- m_SelectOnLeft: {fileID: 0}
- m_SelectOnRight: {fileID: 0}
- m_Transition: 1
- m_Colors:
- m_NormalColor: {r: 0.32156864, g: 0.32156864, b: 0.32156864, a: 1}
- m_HighlightedColor: {r: 0.3529412, g: 0.3529412, b: 0.3529412, a: 1}
- m_PressedColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 1}
- m_DisabledColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 0.2509804}
- m_ColorMultiplier: 1
- m_FadeDuration: 0.1
- m_SpriteState:
- m_HighlightedSprite: {fileID: 0}
- m_PressedSprite: {fileID: 0}
- m_DisabledSprite: {fileID: 0}
- m_AnimationTriggers:
- m_NormalTrigger: Normal
- m_HighlightedTrigger: Highlighted
- m_PressedTrigger: Pressed
- m_DisabledTrigger: Disabled
- m_Interactable: 1
- m_TargetGraphic: {fileID: 1004751480}
- m_OnClick:
- m_PersistentCalls:
- m_Calls: []
---- !u!114 &1004751480
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1004751477}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &1004751481
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1004751477}
- m_CullTransparentMesh: 0
---- !u!1 &1007872740
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1007872741}
- - component: {fileID: 1007872744}
- - component: {fileID: 1007872743}
- m_Layer: 5
- m_Name: TitleBar
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1007872741
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1007872740}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 177548783}
- m_Father: {fileID: 776519261}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 20}
- m_Pivot: {x: 0.5, y: 1}
---- !u!114 &1007872743
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1007872740}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.31764707, g: 0.31764707, b: 0.31764707, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &1007872744
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1007872740}
- m_CullTransparentMesh: 0
---- !u!1 &1052220087
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1052220088}
- - component: {fileID: 1052220090}
- - component: {fileID: 1052220089}
- m_Layer: 5
- m_Name: TextStartServer
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1052220088
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1052220087}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 776519261}
- m_RootOrder: 5
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 0}
- m_AnchoredPosition: {x: 0, y: 40}
- m_SizeDelta: {x: 0, y: 20}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &1052220089
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1052220087}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 1
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Start Server
---- !u!222 &1052220090
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1052220087}
- m_CullTransparentMesh: 0
---- !u!1 &1081204137
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1081204138}
- - component: {fileID: 1081204140}
- - component: {fileID: 1081204139}
- m_Layer: 5
- m_Name: TextConnecting
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1081204138
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1081204137}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1926990971}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0.5}
- m_AnchorMax: {x: 1, y: 0.5}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 20}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &1081204139
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1081204137}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 1
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Connecting...
---- !u!222 &1081204140
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1081204137}
- m_CullTransparentMesh: 0
---- !u!1 &1093045668
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1093045669}
- - component: {fileID: 1093045671}
- - component: {fileID: 1093045670}
- m_Layer: 5
- m_Name: TextTitle
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1093045669
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1093045668}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 747705679}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0.5}
- m_AnchorMax: {x: 1, y: 0.5}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: -36, y: 20}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &1093045670
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1093045668}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.23137255, g: 1, b: 0.6862745, a: 1}
- m_RaycastTarget: 0
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 14
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text:
---- !u!222 &1093045671
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1093045668}
- m_CullTransparentMesh: 0
---- !u!1 &1107091652
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1107091656}
- - component: {fileID: 1107091655}
- - component: {fileID: 1107091654}
- - component: {fileID: 1107091653}
- m_Layer: 0
- m_Name: Ground
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!23 &1107091653
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1107091652}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 4294967295
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 29b49c27a74f145918356859bd7af511, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 1
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!64 &1107091654
-MeshCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1107091652}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 3
- m_Convex: 0
- m_CookingOptions: 14
- m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
---- !u!33 &1107091655
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1107091652}
- m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
---- !u!4 &1107091656
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1107091652}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!224 &1206549608
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 719699535}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 651109222}
- - {fileID: 776519261}
- - {fileID: 1926990971}
- m_Father: {fileID: 1972322034}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 0}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!1 &1282001517
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1282001518}
- - component: {fileID: 1282001520}
- - component: {fileID: 1282001521}
- - component: {fileID: 1282001522}
- m_Layer: 0
- m_Name: NetworkManager
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1282001518
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1282001517}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 5
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &1282001520
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1282001517}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 8aab4c8111b7c411b9b92cf3dbc5bd4e, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- dontDestroyOnLoad: 1
- runInBackground: 1
- startOnHeadless: 1
- serverTickRate: 30
- showDebugMessages: 0
- offlineScene:
- onlineScene:
- transport: {fileID: 1282001521}
- networkAddress: localhost
- maxConnections: 25
- authenticator: {fileID: 0}
- playerPrefab: {fileID: 1916082411674582, guid: 6f43bf5488a7443d19ab2a83c6b91f35,
- type: 3}
- autoCreatePlayer: 1
- playerSpawnMethod: 1
- spawnPrefabs:
- - {fileID: 5890560936853567077, guid: b7dd46dbf38c643f09e206f9fa4be008, type: 3}
---- !u!114 &1282001521
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1282001517}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- OnClientConnected:
- m_PersistentCalls:
- m_Calls: []
- OnClientDataReceived:
- m_PersistentCalls:
- m_Calls: []
- OnClientError:
- m_PersistentCalls:
- m_Calls: []
- OnClientDisconnected:
- m_PersistentCalls:
- m_Calls: []
- OnServerConnected:
- m_PersistentCalls:
- m_Calls: []
- OnServerDataReceived:
- m_PersistentCalls:
- m_Calls: []
- OnServerError:
- m_PersistentCalls:
- m_Calls: []
- OnServerDisconnected:
- m_PersistentCalls:
- m_Calls: []
- port: 7777
- NoDelay: 1
- serverMaxMessageSize: 16384
- clientMaxMessageSize: 16384
---- !u!114 &1282001522
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1282001517}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 69f796b44735c414783d66f47b150c5f, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- listServerIp: 35.243.149.104
- gameServerToListenPort: 8887
- clientToListenPort: 8888
- gameServerTitle: Deathmatch
- mainPanel: {fileID: 719699535}
- content: {fileID: 583153859}
- statusText: {fileID: 712827152}
- slotPrefab: {fileID: 114611570997501482, guid: 611330311f6094567ad2f8012b470129,
- type: 3}
- serverAndPlayButton: {fileID: 1004751479}
- serverOnlyButton: {fileID: 993261495}
- connectingPanel: {fileID: 1926990970}
- connectingText: {fileID: 1081204139}
- connectingCancelButton: {fileID: 276447174}
---- !u!1 &1291804677
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1291804678}
- - component: {fileID: 1291804680}
- - component: {fileID: 1291804679}
- m_Layer: 5
- m_Name: PanelStartServer
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1291804678
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1291804677}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 1004751478}
- - {fileID: 993261494}
- m_Father: {fileID: 776519261}
- m_RootOrder: 6
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 0}
- m_AnchoredPosition: {x: 0, y: 16}
- m_SizeDelta: {x: -4, y: 28}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &1291804679
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1291804677}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.25882354, g: 0.25882354, b: 0.25882354, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &1291804680
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1291804677}
- m_CullTransparentMesh: 0
---- !u!1 &1345848862
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1345848863}
- m_Layer: 5
- m_Name: Sliding Area
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1345848863
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1345848862}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 2064208031}
- m_Father: {fileID: 586458804}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: -20, y: -20}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!1 &1458789072
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1458789073}
- - component: {fileID: 1458789074}
- m_Layer: 0
- m_Name: Spawn
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1458789073
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1458789072}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: -3, y: 0, z: 3}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 9
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &1458789074
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1458789072}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &1501912662
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1501912663}
- - component: {fileID: 1501912664}
- m_Layer: 0
- m_Name: Spawn
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1501912663
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1501912662}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: -3, y: 0, z: -3}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 7
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &1501912664
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1501912662}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &1578438652
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1578438653}
- - component: {fileID: 1578438655}
- - component: {fileID: 1578438654}
- m_Layer: 5
- m_Name: PanelTableHeader
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1578438653
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1578438652}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 232720477}
- - {fileID: 424897550}
- - {fileID: 535675710}
- - {fileID: 354490535}
- - {fileID: 635355837}
- m_Father: {fileID: 776519261}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 1}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: -48}
- m_SizeDelta: {x: 0, y: 20}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &1578438654
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1578438652}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.25882354, g: 0.25882354, b: 0.25882354, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &1578438655
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1578438652}
- m_CullTransparentMesh: 0
---- !u!1 &1680368249
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1680368252}
- - component: {fileID: 1680368251}
- - component: {fileID: 1680368250}
- m_Layer: 0
- m_Name: EventSystem
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!114 &1680368250
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1680368249}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_HorizontalAxis: Horizontal
- m_VerticalAxis: Vertical
- m_SubmitButton: Submit
- m_CancelButton: Cancel
- m_InputActionsPerSecond: 10
- m_RepeatDelay: 0.5
- m_ForceModuleActive: 0
---- !u!114 &1680368251
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1680368249}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_FirstSelected: {fileID: 0}
- m_sendNavigationEvents: 1
- m_DragThreshold: 10
---- !u!4 &1680368252
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1680368249}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1918165880
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1918165881}
- - component: {fileID: 1918165885}
- - component: {fileID: 1918165884}
- - component: {fileID: 1918165883}
- - component: {fileID: 1918165882}
- m_Layer: 5
- m_Name: Scroll View
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1918165881
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1918165880}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 583153859}
- - {fileID: 586458804}
- m_Father: {fileID: 776519261}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: -3}
- m_SizeDelta: {x: -2, y: -106}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &1918165882
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1918165880}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -1200242548, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_ShowMaskGraphic: 1
---- !u!114 &1918165883
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1918165880}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.25882354, g: 0.25882354, b: 0.25882354, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &1918165884
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1918165880}
- m_CullTransparentMesh: 0
---- !u!114 &1918165885
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1918165880}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1367256648, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Content: {fileID: 583153859}
- m_Horizontal: 0
- m_Vertical: 1
- m_MovementType: 2
- m_Elasticity: 0.1
- m_Inertia: 1
- m_DecelerationRate: 0.135
- m_ScrollSensitivity: 1
- m_Viewport: {fileID: 0}
- m_HorizontalScrollbar: {fileID: 0}
- m_VerticalScrollbar: {fileID: 586458805}
- m_HorizontalScrollbarVisibility: 2
- m_VerticalScrollbarVisibility: 1
- m_HorizontalScrollbarSpacing: -3
- m_VerticalScrollbarSpacing: -3
- m_OnValueChanged:
- m_PersistentCalls:
- m_Calls: []
---- !u!1 &1926990970
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1926990971}
- - component: {fileID: 1926990973}
- - component: {fileID: 1926990972}
- m_Layer: 5
- m_Name: ConnectingPanel
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &1926990971
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1926990970}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 747705679}
- - {fileID: 13922437}
- - {fileID: 1081204138}
- - {fileID: 276447173}
- m_Father: {fileID: 1206549608}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0.5, y: 0.5}
- m_AnchorMax: {x: 0.5, y: 0.5}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 250, y: 100}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &1926990972
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1926990970}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.19215687, g: 0.19215687, b: 0.19215687, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &1926990973
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1926990970}
- m_CullTransparentMesh: 0
---- !u!1 &1972322030
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1972322034}
- - component: {fileID: 1972322033}
- - component: {fileID: 1972322032}
- - component: {fileID: 1972322031}
- m_Layer: 5
- m_Name: Canvas
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!114 &1972322031
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1972322030}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_IgnoreReversedGraphics: 1
- m_BlockingObjects: 0
- m_BlockingMask:
- serializedVersion: 2
- m_Bits: 4294967295
---- !u!114 &1972322032
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1972322030}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_UiScaleMode: 0
- m_ReferencePixelsPerUnit: 100
- m_ScaleFactor: 1
- m_ReferenceResolution: {x: 800, y: 600}
- m_ScreenMatchMode: 0
- m_MatchWidthOrHeight: 0
- m_PhysicalUnit: 3
- m_FallbackScreenDPI: 96
- m_DefaultSpriteDPI: 96
- m_DynamicPixelsPerUnit: 1
---- !u!223 &1972322033
-Canvas:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1972322030}
- m_Enabled: 1
- serializedVersion: 3
- m_RenderMode: 0
- m_Camera: {fileID: 0}
- m_PlaneDistance: 100
- m_PixelPerfect: 1
- m_ReceivesEvents: 1
- m_OverrideSorting: 0
- m_OverridePixelPerfect: 0
- m_SortingBucketNormalizedSize: 0
- m_AdditionalShaderChannelsFlag: 0
- m_SortingLayerID: 0
- m_SortingOrder: 0
- m_TargetDisplay: 0
---- !u!224 &1972322034
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1972322030}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 0, y: 0, z: 0}
- m_Children:
- - {fileID: 1206549608}
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 0, y: 0}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 0}
- m_Pivot: {x: 0, y: 0}
---- !u!1 &2020215608
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 2020215609}
- - component: {fileID: 2020215611}
- - component: {fileID: 2020215610}
- m_Layer: 5
- m_Name: Text
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &2020215609
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2020215608}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 993261494}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 0}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &2020215610
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2020215608}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Server Only
---- !u!222 &2020215611
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2020215608}
- m_CullTransparentMesh: 0
---- !u!1 &2054208274
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 2054208276}
- - component: {fileID: 2054208275}
- m_Layer: 0
- m_Name: Directional light
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!108 &2054208275
-Light:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2054208274}
- m_Enabled: 1
- serializedVersion: 8
- m_Type: 1
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_Intensity: 1
- m_Range: 10
- m_SpotAngle: 30
- m_CookieSize: 10
- m_Shadows:
- m_Type: 2
- m_Resolution: -1
- m_CustomResolution: -1
- m_Strength: 1
- m_Bias: 0.05
- m_NormalBias: 0.4
- m_NearPlane: 0.2
- m_Cookie: {fileID: 0}
- m_DrawHalo: 0
- m_Flare: {fileID: 0}
- m_RenderMode: 0
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_Lightmapping: 4
- m_LightShadowCasterMode: 0
- m_AreaSize: {x: 1, y: 1}
- m_BounceIntensity: 1
- m_ColorTemperature: 6570
- m_UseColorTemperature: 0
- m_ShadowRadius: 0
- m_ShadowAngle: 0
---- !u!4 &2054208276
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2054208274}
- m_LocalRotation: {x: 0.10938167, y: 0.8754261, z: -0.40821788, w: 0.23456976}
- m_LocalPosition: {x: 0, y: 10, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 50, y: 150, z: 0}
---- !u!1 &2064208030
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 2064208031}
- - component: {fileID: 2064208033}
- - component: {fileID: 2064208032}
- m_Layer: 5
- m_Name: Handle
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &2064208031
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2064208030}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1345848863}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 0, y: 0}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 20, y: 20}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &2064208032
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2064208030}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!222 &2064208033
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2064208030}
- m_CullTransparentMesh: 0
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/Scene.unity.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/Scene.unity.meta
deleted file mode 100644
index f0b8032..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/Scenes/Scene.unity.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: ccdea83d270df4b078963a0243e41ac0
-timeCreated: 1426587410
-licenseType: Free
-DefaultImporter:
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI.meta
deleted file mode 100644
index 8588770..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 8d7b75cc57dee4425af050c10508257a
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/ServerStatusSlot.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/ServerStatusSlot.prefab
deleted file mode 100644
index 331b4b7..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/ServerStatusSlot.prefab
+++ /dev/null
@@ -1,635 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &1009505356919436
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 224428085307354514}
- - component: {fileID: 222534217462828066}
- - component: {fileID: 114077992825021022}
- m_Layer: 5
- m_Name: TextPlayers
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &224428085307354514
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1009505356919436}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 224813910264502154}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 0, y: 0}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 60, y: 16}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &222534217462828066
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1009505356919436}
- m_CullTransparentMesh: 0
---- !u!114 &114077992825021022
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1009505356919436}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 5
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: '[Players]'
---- !u!1 &1165846264137056
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 224595697833923954}
- - component: {fileID: 222565095748274674}
- - component: {fileID: 114410999938197916}
- m_Layer: 5
- m_Name: TextLatency
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &224595697833923954
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1165846264137056}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 224813910264502154}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 0, y: 0}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 60, y: 16}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &222565095748274674
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1165846264137056}
- m_CullTransparentMesh: 0
---- !u!114 &114410999938197916
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1165846264137056}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 5
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: '[Latency]'
---- !u!1 &1259177336467004
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 224813910264502154}
- - component: {fileID: 222443701544564472}
- - component: {fileID: 114424214131292870}
- - component: {fileID: 114617214395066132}
- - component: {fileID: 114618400118094574}
- - component: {fileID: 114611570997501482}
- m_Layer: 5
- m_Name: ServerStatusSlot
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &224813910264502154
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1259177336467004}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 224596263305646570}
- - {fileID: 224428085307354514}
- - {fileID: 224595697833923954}
- - {fileID: 2588874080615256095}
- - {fileID: 224530003443674914}
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 0, y: 0}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 0}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &222443701544564472
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1259177336467004}
- m_CullTransparentMesh: 0
---- !u!114 &114424214131292870
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1259177336467004}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 0.2509804, g: 0.2509804, b: 0.2509804, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!114 &114617214395066132
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1259177336467004}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1741964061, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_HorizontalFit: 0
- m_VerticalFit: 2
---- !u!114 &114618400118094574
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1259177336467004}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -405508275, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Padding:
- m_Left: 4
- m_Right: 2
- m_Top: 1
- m_Bottom: 1
- m_ChildAlignment: 0
- m_Spacing: 0
- m_ChildForceExpandWidth: 0
- m_ChildForceExpandHeight: 0
- m_ChildControlWidth: 0
- m_ChildControlHeight: 0
---- !u!114 &114611570997501482
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1259177336467004}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 7f24d39c9182b4098bcfd0c2546d0bf2, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- titleText: {fileID: 114105517410707240}
- playersText: {fileID: 114077992825021022}
- latencyText: {fileID: 114410999938197916}
- addressText: {fileID: 1711666012325280996}
- joinButton: {fileID: 114358377111651776}
---- !u!1 &1368168976437814
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 224596263305646570}
- - component: {fileID: 222703717971346548}
- - component: {fileID: 114105517410707240}
- m_Layer: 5
- m_Name: TextTitle
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &224596263305646570
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1368168976437814}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 224813910264502154}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 0, y: 0}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 218, y: 16}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &222703717971346548
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1368168976437814}
- m_CullTransparentMesh: 0
---- !u!114 &114105517410707240
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1368168976437814}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 3
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: '[Title]'
---- !u!1 &1462871638010074
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 224530003443674914}
- - component: {fileID: 222322555260831376}
- - component: {fileID: 114653458098104780}
- - component: {fileID: 114358377111651776}
- m_Layer: 5
- m_Name: ButtonJoin
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &224530003443674914
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1462871638010074}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 224615151935076648}
- m_Father: {fileID: 224813910264502154}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 0, y: 0}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 40, y: 18}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &222322555260831376
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1462871638010074}
- m_CullTransparentMesh: 0
---- !u!114 &114653458098104780
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1462871638010074}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
- m_Type: 1
- m_PreserveAspect: 0
- m_FillCenter: 1
- m_FillMethod: 4
- m_FillAmount: 1
- m_FillClockwise: 1
- m_FillOrigin: 0
- m_UseSpriteMesh: 0
---- !u!114 &114358377111651776
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1462871638010074}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Navigation:
- m_Mode: 3
- m_SelectOnUp: {fileID: 0}
- m_SelectOnDown: {fileID: 0}
- m_SelectOnLeft: {fileID: 0}
- m_SelectOnRight: {fileID: 0}
- m_Transition: 1
- m_Colors:
- m_NormalColor: {r: 0.32156864, g: 0.32156864, b: 0.32156864, a: 1}
- m_HighlightedColor: {r: 0.3529412, g: 0.3529412, b: 0.3529412, a: 1}
- m_PressedColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 1}
- m_DisabledColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 0.37254903}
- m_ColorMultiplier: 1
- m_FadeDuration: 0.1
- m_SpriteState:
- m_HighlightedSprite: {fileID: 0}
- m_PressedSprite: {fileID: 0}
- m_DisabledSprite: {fileID: 0}
- m_AnimationTriggers:
- m_NormalTrigger: Normal
- m_HighlightedTrigger: Highlighted
- m_PressedTrigger: Pressed
- m_DisabledTrigger: Disabled
- m_Interactable: 1
- m_TargetGraphic: {fileID: 114653458098104780}
- m_OnClick:
- m_PersistentCalls:
- m_Calls: []
---- !u!1 &1575165076438694
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 224615151935076648}
- - component: {fileID: 222903696298421472}
- - component: {fileID: 114447744505293664}
- m_Layer: 5
- m_Name: Text
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &224615151935076648
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1575165076438694}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 224530003443674914}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 1, y: 1}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 0, y: 0}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &222903696298421472
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1575165076438694}
- m_CullTransparentMesh: 0
---- !u!114 &114447744505293664
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1575165076438694}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 4
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: Join
---- !u!1 &2231260898927249423
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 2588874080615256095}
- - component: {fileID: 2389080155505640677}
- - component: {fileID: 1711666012325280996}
- m_Layer: 5
- m_Name: TextAddress
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!224 &2588874080615256095
-RectTransform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2231260898927249423}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 224813910264502154}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
- m_AnchorMin: {x: 0, y: 0}
- m_AnchorMax: {x: 0, y: 0}
- m_AnchoredPosition: {x: 0, y: 0}
- m_SizeDelta: {x: 130, y: 16}
- m_Pivot: {x: 0.5, y: 0.5}
---- !u!222 &2389080155505640677
-CanvasRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2231260898927249423}
- m_CullTransparentMesh: 0
---- !u!114 &1711666012325280996
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2231260898927249423}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- m_Material: {fileID: 0}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 1
- m_OnCullStateChanged:
- m_PersistentCalls:
- m_Calls: []
- m_FontData:
- m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
- m_FontSize: 12
- m_FontStyle: 0
- m_BestFit: 0
- m_MinSize: 1
- m_MaxSize: 40
- m_Alignment: 5
- m_AlignByGeometry: 0
- m_RichText: 1
- m_HorizontalOverflow: 0
- m_VerticalOverflow: 0
- m_LineSpacing: 1
- m_Text: '[Address]'
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/ServerStatusSlot.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/ServerStatusSlot.prefab.meta
deleted file mode 100644
index 49ce4ad..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/ServerStatusSlot.prefab.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 611330311f6094567ad2f8012b470129
-PrefabImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs
deleted file mode 100644
index 02efe82..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Attach to the prefab for easier component access by the UI Scripts.
-// Otherwise we would need slot.GetChild(0).GetComponentInChildren etc.
-using UnityEngine;
-using UnityEngine.UI;
-
-public class UIServerStatusSlot : MonoBehaviour
-{
- public Text titleText;
- public Text playersText;
- public Text latencyText;
- public Text addressText;
- public Button joinButton;
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs.meta
deleted file mode 100644
index a3fee6d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 7f24d39c9182b4098bcfd0c2546d0bf2
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong.meta
deleted file mode 100644
index ac8a6e2..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 2220cb06641bd40be8c8330b3b4dd0ee
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/PhysicsMaterials.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/PhysicsMaterials.meta
deleted file mode 100644
index 3ba9985..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/PhysicsMaterials.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 7f122364b93b24938b3f50539de4d746
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/PhysicsMaterials/BallMaterial.physicsMaterial2D b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/PhysicsMaterials/BallMaterial.physicsMaterial2D
deleted file mode 100644
index e2dd2d0..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/PhysicsMaterials/BallMaterial.physicsMaterial2D
+++ /dev/null
@@ -1,10 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!62 &6200000
-PhysicsMaterial2D:
- m_ObjectHideFlags: 0
- m_PrefabParentObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
- m_Name: BallMaterial
- friction: 0
- bounciness: 1
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta
deleted file mode 100644
index 85c1baf..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 97a3e4cddb8635c4eba1265f44d106bf
-timeCreated: 1426602119
-licenseType: Free
-NativeFormatImporter:
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs.meta
deleted file mode 100644
index 7e90f0d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: db1c7e1499ee84bfba33fa7f2cb1bc57
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Ball.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Ball.prefab
deleted file mode 100644
index ea7a7aa..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Ball.prefab
+++ /dev/null
@@ -1,180 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &1080679924113744
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 4700925592147096}
- - component: {fileID: 212107498293566416}
- - component: {fileID: 61279514624852186}
- - component: {fileID: 50354248948880112}
- - component: {fileID: 114290021321007948}
- - component: {fileID: 114692463781779748}
- - component: {fileID: 114121325390084138}
- m_Layer: 0
- m_Name: Ball
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &4700925592147096
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1080679924113744}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: -3, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!212 &212107498293566416
-SpriteRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1080679924113744}
- m_Enabled: 1
- m_CastShadows: 0
- m_ReceiveShadows: 0
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 0
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_Sprite: {fileID: 21300000, guid: 4b66f21097323d44ab40669b2fb9c53d, type: 3}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_FlipX: 0
- m_FlipY: 0
- m_DrawMode: 0
- m_Size: {x: 1, y: 1}
- m_AdaptiveModeThreshold: 0.5
- m_SpriteTileMode: 0
- m_WasSpriteAssigned: 1
- m_MaskInteraction: 0
- m_SpriteSortPoint: 0
---- !u!61 &61279514624852186
-BoxCollider2D:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1080679924113744}
- m_Enabled: 1
- m_Density: 1
- m_Material: {fileID: 6200000, guid: 97a3e4cddb8635c4eba1265f44d106bf, type: 2}
- m_IsTrigger: 0
- m_UsedByEffector: 0
- m_UsedByComposite: 0
- m_Offset: {x: 0, y: 0}
- m_SpriteTilingProperty:
- border: {x: 0, y: 0, z: 0, w: 0}
- pivot: {x: 0.5, y: 0.5}
- oldSize: {x: 1, y: 1}
- newSize: {x: 1, y: 1}
- adaptiveTilingThreshold: 0.5
- drawMode: 0
- adaptiveTiling: 0
- m_AutoTiling: 0
- serializedVersion: 2
- m_Size: {x: 1, y: 1}
- m_EdgeRadius: 0
---- !u!50 &50354248948880112
-Rigidbody2D:
- serializedVersion: 4
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1080679924113744}
- m_BodyType: 0
- m_Simulated: 0
- m_UseFullKinematicContacts: 0
- m_UseAutoMass: 0
- m_Mass: 0.0001
- m_LinearDrag: 0
- m_AngularDrag: 0.05
- m_GravityScale: 0
- m_Material: {fileID: 0}
- m_Interpolate: 0
- m_SleepingMode: 1
- m_CollisionDetection: 0
- m_Constraints: 4
---- !u!114 &114290021321007948
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1080679924113744}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 0
- m_AssetId: 5f7a7f34494ed40268eff49dbf9168bf
- m_SceneId: 0
---- !u!114 &114692463781779748
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1080679924113744}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 38b5c2f743cd8034a8beeebf277c92c1, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- speed: 30
- rigidbody2d: {fileID: 50354248948880112}
---- !u!114 &114121325390084138
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1080679924113744}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0
- compressRotation: 1
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Ball.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Ball.prefab.meta
deleted file mode 100644
index 6322417..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Ball.prefab.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 5f7a7f34494ed40268eff49dbf9168bf
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 100100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Racket.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Racket.prefab
deleted file mode 100644
index 2a52ff7..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Racket.prefab
+++ /dev/null
@@ -1,180 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &1240244544407914
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 4118252415362944}
- - component: {fileID: 212641192162007874}
- - component: {fileID: 61279767645666242}
- - component: {fileID: 50389918509199184}
- - component: {fileID: 114104497298166850}
- - component: {fileID: 114626868563338794}
- - component: {fileID: 114398896143473162}
- m_Layer: 0
- m_Name: Racket
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &4118252415362944
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1240244544407914}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!212 &212641192162007874
-SpriteRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1240244544407914}
- m_Enabled: 1
- m_CastShadows: 0
- m_ReceiveShadows: 0
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 0
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_Sprite: {fileID: 21300000, guid: 619ccff3ba2f2a04f9ddd19c264a1ecd, type: 3}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_FlipX: 0
- m_FlipY: 0
- m_DrawMode: 0
- m_Size: {x: 1, y: 1}
- m_AdaptiveModeThreshold: 0.5
- m_SpriteTileMode: 0
- m_WasSpriteAssigned: 1
- m_MaskInteraction: 0
- m_SpriteSortPoint: 0
---- !u!61 &61279767645666242
-BoxCollider2D:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1240244544407914}
- m_Enabled: 1
- m_Density: 1
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_UsedByEffector: 0
- m_UsedByComposite: 0
- m_Offset: {x: 0, y: 0}
- m_SpriteTilingProperty:
- border: {x: 0, y: 0, z: 0, w: 0}
- pivot: {x: 0.5, y: 0.5}
- oldSize: {x: 2, y: 4}
- newSize: {x: 1, y: 1}
- adaptiveTilingThreshold: 0.5
- drawMode: 0
- adaptiveTiling: 0
- m_AutoTiling: 0
- serializedVersion: 2
- m_Size: {x: 2, y: 4}
- m_EdgeRadius: 0
---- !u!50 &50389918509199184
-Rigidbody2D:
- serializedVersion: 4
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1240244544407914}
- m_BodyType: 0
- m_Simulated: 1
- m_UseFullKinematicContacts: 0
- m_UseAutoMass: 0
- m_Mass: 1
- m_LinearDrag: 0
- m_AngularDrag: 0.05
- m_GravityScale: 0
- m_Material: {fileID: 0}
- m_Interpolate: 1
- m_SleepingMode: 1
- m_CollisionDetection: 1
- m_Constraints: 4
---- !u!114 &114104497298166850
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1240244544407914}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 1
- m_AssetId: b1651eaf8c7564a1c86031dfbb8a7b28
- m_SceneId: 0
---- !u!114 &114626868563338794
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1240244544407914}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 0748c7eda22b19845b9ce0e4d23d1021, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- speed: 1500
- rigidbody2d: {fileID: 50389918509199184}
---- !u!114 &114398896143473162
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1240244544407914}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0
- compressRotation: 1
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Racket.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Racket.prefab.meta
deleted file mode 100644
index c67ac8f..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Prefabs/Racket.prefab.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: b1651eaf8c7564a1c86031dfbb8a7b28
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 100100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scenes.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scenes.meta
deleted file mode 100644
index ba5b4d4..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scenes.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 00c56c45628954f44aa4d944cbd9bfca
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scenes/Scene.unity b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scenes/Scene.unity
deleted file mode 100644
index 8ffe2b4..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scenes/Scene.unity
+++ /dev/null
@@ -1,942 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!29 &1
-OcclusionCullingSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_OcclusionBakeSettings:
- smallestOccluder: 5
- smallestHole: 0.25
- backfaceThreshold: 100
- m_SceneGUID: 00000000000000000000000000000000
- m_OcclusionCullingData: {fileID: 0}
---- !u!104 &2
-RenderSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 9
- m_Fog: 0
- m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
- m_FogMode: 3
- m_FogDensity: 0.01
- m_LinearFogStart: 0
- m_LinearFogEnd: 300
- m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
- m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
- m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
- m_AmbientIntensity: 1
- m_AmbientMode: 3
- m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
- m_SkyboxMaterial: {fileID: 0}
- m_HaloStrength: 0.5
- m_FlareStrength: 1
- m_FlareFadeSpeed: 3
- m_HaloTexture: {fileID: 0}
- m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
- m_DefaultReflectionMode: 0
- m_DefaultReflectionResolution: 128
- m_ReflectionBounces: 1
- m_ReflectionIntensity: 1
- m_CustomReflection: {fileID: 0}
- m_Sun: {fileID: 0}
- m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
- m_UseRadianceAmbientProbe: 0
---- !u!157 &4
-LightmapSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 11
- m_GIWorkflowMode: 0
- m_GISettings:
- serializedVersion: 2
- m_BounceScale: 1
- m_IndirectOutputScale: 1
- m_AlbedoBoost: 1
- m_EnvironmentLightingMode: 0
- m_EnableBakedLightmaps: 0
- m_EnableRealtimeLightmaps: 0
- m_LightmapEditorSettings:
- serializedVersion: 10
- m_Resolution: 2
- m_BakeResolution: 40
- m_AtlasSize: 1024
- m_AO: 0
- m_AOMaxDistance: 1
- m_CompAOExponent: 0
- m_CompAOExponentDirect: 0
- m_Padding: 2
- m_LightmapParameters: {fileID: 0}
- m_LightmapsBakeMode: 1
- m_TextureCompression: 1
- m_FinalGather: 0
- m_FinalGatherFiltering: 1
- m_FinalGatherRayCount: 1024
- m_ReflectionCompression: 2
- m_MixedBakeMode: 1
- m_BakeBackend: 0
- m_PVRSampling: 1
- m_PVRDirectSampleCount: 32
- m_PVRSampleCount: 500
- m_PVRBounces: 2
- m_PVRFilterTypeDirect: 0
- m_PVRFilterTypeIndirect: 0
- m_PVRFilterTypeAO: 0
- m_PVRFilteringMode: 0
- m_PVRCulling: 1
- m_PVRFilteringGaussRadiusDirect: 1
- m_PVRFilteringGaussRadiusIndirect: 5
- m_PVRFilteringGaussRadiusAO: 2
- m_PVRFilteringAtrousPositionSigmaDirect: 0.5
- m_PVRFilteringAtrousPositionSigmaIndirect: 2
- m_PVRFilteringAtrousPositionSigmaAO: 1
- m_ShowResolutionOverlay: 1
- m_LightingDataAsset: {fileID: 0}
- m_UseShadowmask: 0
---- !u!196 &5
-NavMeshSettings:
- serializedVersion: 2
- m_ObjectHideFlags: 0
- m_BuildSettings:
- serializedVersion: 2
- agentTypeID: 0
- agentRadius: 0.5
- agentHeight: 2
- agentSlope: 45
- agentClimb: 0.4
- ledgeDropHeight: 0
- maxJumpAcrossDistance: 0
- minRegionArea: 2
- manualCellSize: 0
- cellSize: 0.16666667
- manualTileSize: 0
- tileSize: 256
- accuratePlacement: 0
- debug:
- m_Flags: 0
- m_NavMeshData: {fileID: 0}
---- !u!1 &289876230
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 289876232}
- - component: {fileID: 289876231}
- m_Layer: 0
- m_Name: DottedLine
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!212 &289876231
-SpriteRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 289876230}
- m_Enabled: 1
- m_CastShadows: 0
- m_ReceiveShadows: 0
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 0
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_Sprite: {fileID: 21300000, guid: 1b5c0b514d8b2d24091d5aec516fe860, type: 3}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_FlipX: 0
- m_FlipY: 0
- m_DrawMode: 0
- m_Size: {x: 1, y: 1}
- m_AdaptiveModeThreshold: 0.5
- m_SpriteTileMode: 0
- m_WasSpriteAssigned: 1
- m_MaskInteraction: 0
- m_SpriteSortPoint: 0
---- !u!4 &289876232
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 289876230}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1607538195}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &473997959
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 473997961}
- m_Layer: 0
- m_Name: RacketSpawnLeft
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &473997961
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 473997959}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: -20, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &753891880
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 753891882}
- - component: {fileID: 753891881}
- - component: {fileID: 753891883}
- m_Layer: 0
- m_Name: WallBottom
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!212 &753891881
-SpriteRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 753891880}
- m_Enabled: 1
- m_CastShadows: 0
- m_ReceiveShadows: 0
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 0
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_Sprite: {fileID: 21300000, guid: b931587800e08c54aa8dbbd6c15c894f, type: 3}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_FlipX: 0
- m_FlipY: 0
- m_DrawMode: 0
- m_Size: {x: 1, y: 1}
- m_AdaptiveModeThreshold: 0.5
- m_SpriteTileMode: 0
- m_WasSpriteAssigned: 1
- m_MaskInteraction: 0
- m_SpriteSortPoint: 0
---- !u!4 &753891882
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 753891880}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: -16, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1607538195}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!61 &753891883
-BoxCollider2D:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 753891880}
- m_Enabled: 1
- m_Density: 1
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_UsedByEffector: 0
- m_UsedByComposite: 0
- m_Offset: {x: 0, y: 0}
- m_SpriteTilingProperty:
- border: {x: 0, y: 0, z: 0, w: 0}
- pivot: {x: 0.5, y: 0.5}
- oldSize: {x: 50, y: 1}
- newSize: {x: 1, y: 1}
- adaptiveTilingThreshold: 0.5
- drawMode: 0
- adaptiveTiling: 0
- m_AutoTiling: 0
- serializedVersion: 2
- m_Size: {x: 50, y: 1}
- m_EdgeRadius: 0
---- !u!1 &1346799726
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1346799731}
- - component: {fileID: 1346799730}
- - component: {fileID: 1346799729}
- - component: {fileID: 1346799728}
- - component: {fileID: 1346799727}
- m_Layer: 0
- m_Name: Main Camera
- m_TagString: MainCamera
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!81 &1346799727
-AudioListener:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1346799726}
- m_Enabled: 1
---- !u!124 &1346799728
-Behaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1346799726}
- m_Enabled: 1
---- !u!92 &1346799729
-Behaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1346799726}
- m_Enabled: 1
---- !u!20 &1346799730
-Camera:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1346799726}
- m_Enabled: 1
- serializedVersion: 2
- m_ClearFlags: 1
- m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0.019607844}
- m_projectionMatrixMode: 1
- m_SensorSize: {x: 36, y: 24}
- m_LensShift: {x: 0, y: 0}
- m_GateFitMode: 2
- m_FocalLength: 50
- m_NormalizedViewPortRect:
- serializedVersion: 2
- x: 0
- y: 0
- width: 1
- height: 1
- near clip plane: 0.3
- far clip plane: 1000
- field of view: 60
- orthographic: 1
- orthographic size: 40
- m_Depth: -1
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_RenderingPath: -1
- m_TargetTexture: {fileID: 0}
- m_TargetDisplay: 0
- m_TargetEye: 3
- m_HDR: 0
- m_AllowMSAA: 1
- m_AllowDynamicResolution: 0
- m_ForceIntoRT: 0
- m_OcclusionCulling: 1
- m_StereoConvergence: 10
- m_StereoSeparation: 0.022
---- !u!4 &1346799731
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1346799726}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: -10}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1352350029
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1352350031}
- - component: {fileID: 1352350030}
- - component: {fileID: 1352350032}
- m_Layer: 0
- m_Name: WallLeft
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!212 &1352350030
-SpriteRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1352350029}
- m_Enabled: 1
- m_CastShadows: 0
- m_ReceiveShadows: 0
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 0
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_Sprite: {fileID: 21300000, guid: 0f2833a292a197d4fb0385a8efa1dc91, type: 3}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_FlipX: 0
- m_FlipY: 0
- m_DrawMode: 0
- m_Size: {x: 1, y: 1}
- m_AdaptiveModeThreshold: 0.5
- m_SpriteTileMode: 0
- m_WasSpriteAssigned: 1
- m_MaskInteraction: 0
- m_SpriteSortPoint: 0
---- !u!4 &1352350031
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1352350029}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: -24.5, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1607538195}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!61 &1352350032
-BoxCollider2D:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1352350029}
- m_Enabled: 1
- m_Density: 1
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_UsedByEffector: 0
- m_UsedByComposite: 0
- m_Offset: {x: 0, y: 0}
- m_SpriteTilingProperty:
- border: {x: 0, y: 0, z: 0, w: 0}
- pivot: {x: 0.5, y: 0.5}
- oldSize: {x: 1, y: 32}
- newSize: {x: 1, y: 1}
- adaptiveTilingThreshold: 0.5
- drawMode: 0
- adaptiveTiling: 0
- m_AutoTiling: 0
- serializedVersion: 2
- m_Size: {x: 1, y: 32}
- m_EdgeRadius: 0
---- !u!1 &1368547944
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1368547946}
- - component: {fileID: 1368547945}
- - component: {fileID: 1368547947}
- m_Layer: 0
- m_Name: WallTop
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!212 &1368547945
-SpriteRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1368547944}
- m_Enabled: 1
- m_CastShadows: 0
- m_ReceiveShadows: 0
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 0
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_Sprite: {fileID: 21300000, guid: b931587800e08c54aa8dbbd6c15c894f, type: 3}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_FlipX: 0
- m_FlipY: 0
- m_DrawMode: 0
- m_Size: {x: 1, y: 1}
- m_AdaptiveModeThreshold: 0.5
- m_SpriteTileMode: 0
- m_WasSpriteAssigned: 1
- m_MaskInteraction: 0
- m_SpriteSortPoint: 0
---- !u!4 &1368547946
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1368547944}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 16, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1607538195}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!61 &1368547947
-BoxCollider2D:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1368547944}
- m_Enabled: 1
- m_Density: 1
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_UsedByEffector: 0
- m_UsedByComposite: 0
- m_Offset: {x: 0, y: 0}
- m_SpriteTilingProperty:
- border: {x: 0, y: 0, z: 0, w: 0}
- pivot: {x: 0.5, y: 0.5}
- oldSize: {x: 50, y: 1}
- newSize: {x: 1, y: 1}
- adaptiveTilingThreshold: 0.5
- drawMode: 0
- adaptiveTiling: 0
- m_AutoTiling: 0
- serializedVersion: 2
- m_Size: {x: 50, y: 1}
- m_EdgeRadius: 0
---- !u!1 &1397990094
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1397990096}
- m_Layer: 0
- m_Name: RacketSpawnRight
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1397990096
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1397990094}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 20, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1575697329
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1575697331}
- - component: {fileID: 1575697330}
- - component: {fileID: 1575697332}
- m_Layer: 0
- m_Name: WallRight
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!212 &1575697330
-SpriteRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1575697329}
- m_Enabled: 1
- m_CastShadows: 0
- m_ReceiveShadows: 0
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 0
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_Sprite: {fileID: 21300000, guid: 0f2833a292a197d4fb0385a8efa1dc91, type: 3}
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_FlipX: 0
- m_FlipY: 0
- m_DrawMode: 0
- m_Size: {x: 1, y: 1}
- m_AdaptiveModeThreshold: 0.5
- m_SpriteTileMode: 0
- m_WasSpriteAssigned: 1
- m_MaskInteraction: 0
- m_SpriteSortPoint: 0
---- !u!4 &1575697331
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1575697329}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 24.5, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1607538195}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!61 &1575697332
-BoxCollider2D:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1575697329}
- m_Enabled: 1
- m_Density: 1
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_UsedByEffector: 0
- m_UsedByComposite: 0
- m_Offset: {x: 0, y: 0}
- m_SpriteTilingProperty:
- border: {x: 0, y: 0, z: 0, w: 0}
- pivot: {x: 0.5, y: 0.5}
- oldSize: {x: 1, y: 32}
- newSize: {x: 1, y: 1}
- adaptiveTilingThreshold: 0.5
- drawMode: 0
- adaptiveTiling: 0
- m_AutoTiling: 0
- serializedVersion: 2
- m_Size: {x: 1, y: 32}
- m_EdgeRadius: 0
---- !u!1 &1607538194
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1607538195}
- m_Layer: 0
- m_Name: Table
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1607538195
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1607538194}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 1368547946}
- - {fileID: 753891882}
- - {fileID: 1575697331}
- - {fileID: 1352350031}
- - {fileID: 289876232}
- m_Father: {fileID: 0}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1886246549
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1886246550}
- - component: {fileID: 1886246552}
- - component: {fileID: 1886246551}
- - component: {fileID: 1886246553}
- m_Layer: 0
- m_Name: NetworkManager
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1886246550
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1886246549}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &1886246551
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1886246549}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 6442dc8070ceb41f094e44de0bf87274, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- showGUI: 1
- offsetX: 0
- offsetY: 0
---- !u!114 &1886246552
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1886246549}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 0aa3018bb284840d6a6d0acee29ab098, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- dontDestroyOnLoad: 1
- runInBackground: 1
- startOnHeadless: 1
- serverTickRate: 30
- showDebugMessages: 0
- offlineScene:
- onlineScene:
- transport: {fileID: 1886246553}
- networkAddress: localhost
- maxConnections: 4
- playerPrefab: {fileID: 1240244544407914, guid: b1651eaf8c7564a1c86031dfbb8a7b28,
- type: 3}
- autoCreatePlayer: 1
- playerSpawnMethod: 1
- spawnPrefabs:
- - {fileID: 1080679924113744, guid: 5f7a7f34494ed40268eff49dbf9168bf, type: 3}
- leftRacketSpawn: {fileID: 473997961}
- rightRacketSpawn: {fileID: 1397990096}
---- !u!114 &1886246553
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1886246549}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- OnClientConnected:
- m_PersistentCalls:
- m_Calls: []
- m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0,
- Culture=neutral, PublicKeyToken=null
- OnClientDataReceived:
- m_PersistentCalls:
- m_Calls: []
- m_TypeName: Mirror.UnityEventByteArray, Mirror, Version=0.0.0.0, Culture=neutral,
- PublicKeyToken=null
- OnClientError:
- m_PersistentCalls:
- m_Calls: []
- m_TypeName: Mirror.UnityEventException, Mirror, Version=0.0.0.0, Culture=neutral,
- PublicKeyToken=null
- OnClientDisconnected:
- m_PersistentCalls:
- m_Calls: []
- m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0,
- Culture=neutral, PublicKeyToken=null
- OnServerConnected:
- m_PersistentCalls:
- m_Calls: []
- m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
- OnServerDataReceived:
- m_PersistentCalls:
- m_Calls: []
- m_TypeName: Mirror.UnityEventIntByteArray, Mirror, Version=0.0.0.0, Culture=neutral,
- PublicKeyToken=null
- OnServerError:
- m_PersistentCalls:
- m_Calls: []
- m_TypeName: Mirror.UnityEventIntException, Mirror, Version=0.0.0.0, Culture=neutral,
- PublicKeyToken=null
- OnServerDisconnected:
- m_PersistentCalls:
- m_Calls: []
- m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
- port: 7777
- NoDelay: 1
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scenes/Scene.unity.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scenes/Scene.unity.meta
deleted file mode 100644
index 88cc8f1..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scenes/Scene.unity.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 89a84548859e3b643b4fb27984dc2b0d
-timeCreated: 1426587410
-licenseType: Free
-DefaultImporter:
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts.meta
deleted file mode 100644
index b482c47..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 55e7bd9b7212f4318909cbca3bdb1284
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Ball.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Ball.cs
deleted file mode 100644
index 69adbf1..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Ball.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using UnityEngine;
-
-namespace Mirror.Examples.Pong
-{
- public class Ball : NetworkBehaviour
- {
- public float speed = 30;
- public Rigidbody2D rigidbody2d;
-
- public override void OnStartServer()
- {
- base.OnStartServer();
-
- // only simulate ball physics on server
- rigidbody2d.simulated = true;
-
- // Serve the ball from left player
- rigidbody2d.velocity = Vector2.right * speed;
- }
-
- float HitFactor(Vector2 ballPos, Vector2 racketPos, float racketHeight)
- {
- // ascii art:
- // || 1 <- at the top of the racket
- // ||
- // || 0 <- at the middle of the racket
- // ||
- // || -1 <- at the bottom of the racket
- return (ballPos.y - racketPos.y) / racketHeight;
- }
-
- [ServerCallback] // only call this on server
- void OnCollisionEnter2D(Collision2D col)
- {
- // Note: 'col' holds the collision information. If the
- // Ball collided with a racket, then:
- // col.gameObject is the racket
- // col.transform.position is the racket's position
- // col.collider is the racket's collider
-
- // did we hit a racket? then we need to calculate the hit factor
- if (col.transform.GetComponent())
- {
- // Calculate y direction via hit Factor
- float y = HitFactor(transform.position,
- col.transform.position,
- col.collider.bounds.size.y);
-
- // Calculate x direction via opposite collision
- float x = col.relativeVelocity.x > 0 ? 1 : -1;
-
- // Calculate direction, make length=1 via .normalized
- Vector2 dir = new Vector2(x, y).normalized;
-
- // Set Velocity with dir * speed
- rigidbody2d.velocity = dir * speed;
- }
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Ball.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Ball.cs.meta
deleted file mode 100644
index 1eb956d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Ball.cs.meta
+++ /dev/null
@@ -1,12 +0,0 @@
-fileFormatVersion: 2
-guid: 38b5c2f743cd8034a8beeebf277c92c1
-timeCreated: 1426602353
-licenseType: Free
-MonoImporter:
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/NetworkManagerPong.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/NetworkManagerPong.cs
deleted file mode 100644
index a8869ff..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/NetworkManagerPong.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using UnityEngine;
-using Mirror;
-
-// Custom NetworkManager that simply assigns the correct racket positions when
-// spawning players. The built in RoundRobin spawn method wouldn't work after
-// someone reconnects (both players would be on the same side).
-public class NetworkManagerPong : NetworkManager
-{
- public Transform leftRacketSpawn;
- public Transform rightRacketSpawn;
- GameObject ball;
-
- public override void OnServerAddPlayer(NetworkConnection conn)
- {
- // add player at correct spawn position
- Transform start = numPlayers == 0 ? leftRacketSpawn : rightRacketSpawn;
- GameObject player = Instantiate(playerPrefab, start.position, start.rotation);
- NetworkServer.AddPlayerForConnection(conn, player);
-
- // spawn ball if two players
- if (numPlayers == 2)
- {
- ball = Instantiate(spawnPrefabs.Find(prefab => prefab.name == "Ball"));
- NetworkServer.Spawn(ball);
- }
- }
-
- public override void OnServerDisconnect(NetworkConnection conn)
- {
- // destroy ball
- if (ball != null)
- NetworkServer.Destroy(ball);
-
- // call base functionality (actually destroys the player)
- base.OnServerDisconnect(conn);
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/NetworkManagerPong.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/NetworkManagerPong.cs.meta
deleted file mode 100644
index 4b191ea..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/NetworkManagerPong.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 0aa3018bb284840d6a6d0acee29ab098
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Player.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Player.cs
deleted file mode 100644
index 5de9320..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Player.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using UnityEngine;
-
-namespace Mirror.Examples.Pong
-{
- public class Player : NetworkBehaviour
- {
- public float speed = 30;
- public Rigidbody2D rigidbody2d;
-
- // need to use FixedUpdate for rigidbody
- void FixedUpdate()
- {
- // only let the local player control the racket.
- // don't control other player's rackets
- if (isLocalPlayer)
- rigidbody2d.velocity = Time.fixedDeltaTime * speed * new Vector2(0, Input.GetAxisRaw("Vertical"));
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Player.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Player.cs.meta
deleted file mode 100644
index 15c309e..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Scripts/Player.cs.meta
+++ /dev/null
@@ -1,12 +0,0 @@
-fileFormatVersion: 2
-guid: 0748c7eda22b19845b9ce0e4d23d1021
-timeCreated: 1426597826
-licenseType: Free
-MonoImporter:
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites.meta
deleted file mode 100644
index 42350a3..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 9d39b68545c2e43cfa4a37f6703a983b
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Ball.png b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Ball.png
deleted file mode 100644
index 20c4387..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Ball.png and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Ball.png.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Ball.png.meta
deleted file mode 100644
index 040bba3..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Ball.png.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: 4b66f21097323d44ab40669b2fb9c53d
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 9
- mipmaps:
- mipMapMode: 0
- enableMipMap: 0
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: -3
- maxTextureSize: 2048
- textureSettings:
- serializedVersion: 2
- filterMode: 0
- aniso: 16
- mipBias: -100
- wrapU: 1
- wrapV: 1
- wrapW: 1
- nPOTScale: 0
- lightmap: 0
- compressionQuality: 50
- spriteMode: 1
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 1
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 1
- spriteTessellationDetail: -1
- textureType: 8
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 2048
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 0
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID: c5a291323e0d5f34883a55625f66ca70
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/DottedLine.png b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/DottedLine.png
deleted file mode 100644
index 0bcab09..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/DottedLine.png and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/DottedLine.png.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/DottedLine.png.meta
deleted file mode 100644
index 993c831..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/DottedLine.png.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: 1b5c0b514d8b2d24091d5aec516fe860
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 9
- mipmaps:
- mipMapMode: 0
- enableMipMap: 0
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: -3
- maxTextureSize: 2048
- textureSettings:
- serializedVersion: 2
- filterMode: 0
- aniso: 16
- mipBias: -100
- wrapU: 1
- wrapV: 1
- wrapW: 1
- nPOTScale: 0
- lightmap: 0
- compressionQuality: 50
- spriteMode: 1
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 1
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 1
- spriteTessellationDetail: -1
- textureType: 8
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 2048
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 0
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID: 98b4e2aa86aa3d843821adfe71dbbac0
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Racket.png b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Racket.png
deleted file mode 100644
index c73938d..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Racket.png and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Racket.png.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Racket.png.meta
deleted file mode 100644
index 47b9fc8..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/Sprites/Racket.png.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: 619ccff3ba2f2a04f9ddd19c264a1ecd
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 9
- mipmaps:
- mipMapMode: 0
- enableMipMap: 0
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: -3
- maxTextureSize: 2048
- textureSettings:
- serializedVersion: 2
- filterMode: 0
- aniso: 16
- mipBias: -100
- wrapU: 1
- wrapV: 1
- wrapW: 1
- nPOTScale: 0
- lightmap: 0
- compressionQuality: 50
- spriteMode: 1
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 1
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 1
- spriteTessellationDetail: -1
- textureType: 8
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 2048
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 0
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID: 09819c66a21defd49b2cfc87fea685d2
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallHorizontal.png b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallHorizontal.png
deleted file mode 100644
index 6bb5dc3..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallHorizontal.png and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallHorizontal.png.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallHorizontal.png.meta
deleted file mode 100644
index 10afcfc..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallHorizontal.png.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: b931587800e08c54aa8dbbd6c15c894f
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 9
- mipmaps:
- mipMapMode: 0
- enableMipMap: 0
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: -3
- maxTextureSize: 2048
- textureSettings:
- serializedVersion: 2
- filterMode: 0
- aniso: 16
- mipBias: -100
- wrapU: 1
- wrapV: 1
- wrapW: 1
- nPOTScale: 0
- lightmap: 0
- compressionQuality: 50
- spriteMode: 1
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 1
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 1
- spriteTessellationDetail: -1
- textureType: 8
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 2048
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 0
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID: 74c5541eed52f67428025c83260d8bec
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallVertical.png b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallVertical.png
deleted file mode 100644
index 32406c1..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallVertical.png and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallVertical.png.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallVertical.png.meta
deleted file mode 100644
index 9b191ee..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Pong/WallVertical.png.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: 0f2833a292a197d4fb0385a8efa1dc91
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 9
- mipmaps:
- mipMapMode: 0
- enableMipMap: 0
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: -3
- maxTextureSize: 2048
- textureSettings:
- serializedVersion: 2
- filterMode: 0
- aniso: 16
- mipBias: -100
- wrapU: 1
- wrapV: 1
- wrapW: 1
- nPOTScale: 0
- lightmap: 0
- compressionQuality: 50
- spriteMode: 1
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 1
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 1
- spriteTessellationDetail: -1
- textureType: 8
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 2048
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 0
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID: 3a92f998f14389948aa928ac64e8e426
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room.meta
deleted file mode 100644
index 51c8ec2..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: ba0822b68f209a743bc575c6f2cc78f0
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials.meta
deleted file mode 100644
index 1593571..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 177a490b498134246b6eeddfeb608b94
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/PlayArea.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/PlayArea.mat
deleted file mode 100644
index 652213d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/PlayArea.mat
+++ /dev/null
@@ -1,76 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
- m_Name: PlayArea
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords: _GLOSSYREFLECTIONS_OFF _NORMALMAP _SPECULARHIGHLIGHTS_OFF
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 2800000, guid: 1ef4aad253cf7e9488305da905643f09, type: 3}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 8, y: 8}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 2800000, guid: 0ce4715b95ec59e4ca799c740a5e144a, type: 3}
- m_Scale: {x: 8, y: 8}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0.5
- - _GlossyReflections: 0
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 0
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 0.8867924, g: 0.84346247, b: 0.7654859, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/PlayArea.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/PlayArea.mat.meta
deleted file mode 100644
index 093bbc4..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/PlayArea.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 3201636fa507dad448e9a36d66a80825
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Player.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Player.mat
deleted file mode 100644
index 3b0bbe1..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Player.mat
+++ /dev/null
@@ -1,76 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
- m_Name: Player
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0.5
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 0, g: 0, b: 0, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Player.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Player.mat.meta
deleted file mode 100644
index 46963af..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Player.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: ac64a68d9ea8fa9459ff2f158065c1d0
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Prize.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Prize.mat
deleted file mode 100644
index de7f29f..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Prize.mat
+++ /dev/null
@@ -1,76 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
- m_Name: Prize
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0.5
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 0, g: 0, b: 0, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Prize.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Prize.mat.meta
deleted file mode 100644
index 18935a5..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Prize.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: a1d7c9f39b41d414d86e64f7761cd545
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures.meta
deleted file mode 100644
index 0ab7902..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 047a5014adf04914f9ffded62a715e39
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01.tga b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01.tga
deleted file mode 100644
index 52fb755..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01.tga and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01.tga.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01.tga.meta
deleted file mode 100644
index e48bd95..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01.tga.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: 0ce4715b95ec59e4ca799c740a5e144a
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 7
- mipmaps:
- mipMapMode: 0
- enableMipMap: 1
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: -1
- maxTextureSize: 1024
- textureSettings:
- serializedVersion: 2
- filterMode: -1
- aniso: -1
- mipBias: -100
- wrapU: -1
- wrapV: -1
- wrapW: -1
- nPOTScale: 1
- lightmap: 0
- compressionQuality: 50
- spriteMode: 0
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 100
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 0
- spriteTessellationDetail: -1
- textureType: 0
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 1024
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 1
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID:
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01_n.tga b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01_n.tga
deleted file mode 100644
index c3899ab..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01_n.tga and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01_n.tga.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01_n.tga.meta
deleted file mode 100644
index 1e69eda..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Materials/Textures/Wall01_n.tga.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: 1ef4aad253cf7e9488305da905643f09
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 7
- mipmaps:
- mipMapMode: 0
- enableMipMap: 1
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 1
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: -1
- maxTextureSize: 1024
- textureSettings:
- serializedVersion: 2
- filterMode: -1
- aniso: -1
- mipBias: -100
- wrapU: -1
- wrapV: -1
- wrapW: -1
- nPOTScale: 1
- lightmap: 0
- compressionQuality: 50
- spriteMode: 0
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 100
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 0
- spriteTessellationDetail: -1
- textureType: 1
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 1024
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 1
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID:
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs.meta
deleted file mode 100644
index 78f4e75..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 9a6e603a7f407ec4aa25ac2c2799f71b
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/GamePlayer.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/GamePlayer.prefab
deleted file mode 100644
index 06f33b3..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/GamePlayer.prefab
+++ /dev/null
@@ -1,238 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &1430875437483682
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 4216737524944602}
- - component: {fileID: 33190644788701022}
- - component: {fileID: 23708975923909982}
- m_Layer: 0
- m_Name: Visor
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &4216737524944602
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1430875437483682}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0.4, z: 0.505}
- m_LocalScale: {x: 0.5, y: 0.1, z: 0.2}
- m_Children: []
- m_Father: {fileID: 4822224316094678}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &33190644788701022
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1430875437483682}
- m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &23708975923909982
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1430875437483682}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 4294967295
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!1 &1480027675339556
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 4822224316094678}
- - component: {fileID: 33762848230157288}
- - component: {fileID: 23313067197120050}
- - component: {fileID: 143011667059871024}
- - component: {fileID: 114402732107420660}
- - component: {fileID: 114892629901890886}
- - component: {fileID: 114265392388239132}
- m_Layer: 0
- m_Name: GamePlayer
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &4822224316094678
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1480027675339556}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 4216737524944602}
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &33762848230157288
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1480027675339556}
- m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &23313067197120050
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1480027675339556}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 4294967295
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: ac64a68d9ea8fa9459ff2f158065c1d0, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!143 &143011667059871024
-CharacterController:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1480027675339556}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Height: 2
- m_Radius: 0.5
- m_SlopeLimit: 45
- m_StepOffset: 0.3
- m_SkinWidth: 0.08
- m_MinMoveDistance: 0.001
- m_Center: {x: 0, y: 0, z: 0}
---- !u!114 &114402732107420660
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1480027675339556}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 1
- m_AssetId: 21daf89214c6ee443ad6875b73083c60
- m_SceneId: 0
---- !u!114 &114892629901890886
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1480027675339556}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 24fd13686a451ad498101a604d134e39, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0
- index: 0
- score: 0
- playerColor: {r: 0, g: 0, b: 0, a: 1}
- moveSpeed: 8
- turnSpeedAccel: 5
- turnSpeedDecel: 5
- maxTurnSpeed: 150
- jumpSpeed: 0
- jumpFactor: 0.025
- horizontal: 0
- vertical: 0
- turn: 0
- isGrounded: 1
- isFalling: 0
---- !u!114 &114265392388239132
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1480027675339556}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0
- compressRotation: 1
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/GamePlayer.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/GamePlayer.prefab.meta
deleted file mode 100644
index 0df6ef0..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/GamePlayer.prefab.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 21daf89214c6ee443ad6875b73083c60
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 100100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/Prize.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/Prize.prefab
deleted file mode 100644
index 809d919..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/Prize.prefab
+++ /dev/null
@@ -1,128 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &1139254171913846
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 4362442735993418}
- - component: {fileID: 33086497388294428}
- - component: {fileID: 23203154358629070}
- - component: {fileID: 135606878775227198}
- - component: {fileID: 114048121767222990}
- - component: {fileID: 114251241889735402}
- m_Layer: 0
- m_Name: Prize
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!4 &4362442735993418
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1139254171913846}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1, z: 0}
- m_LocalScale: {x: 0.3, y: 0.3, z: 0.3}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!33 &33086497388294428
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1139254171913846}
- m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &23203154358629070
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1139254171913846}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 4294967295
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: a1d7c9f39b41d414d86e64f7761cd545, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!135 &135606878775227198
-SphereCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1139254171913846}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Radius: 0.5
- m_Center: {x: 0, y: 0, z: 0}
---- !u!114 &114048121767222990
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1139254171913846}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: a22f9eb8ebad79e47babf4c051a714ee, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- prizeColor: {r: 0, g: 0, b: 0, a: 1}
- available: 1
- spawner: {fileID: 0}
---- !u!114 &114251241889735402
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1139254171913846}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 0
- m_AssetId: 52f1c9ea06cfd154cb68ff9d1b66fc13
- m_SceneId: 0
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/Prize.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/Prize.prefab.meta
deleted file mode 100644
index 87ab623..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/Prize.prefab.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 52f1c9ea06cfd154cb68ff9d1b66fc13
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 100100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/RoomPlayer.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/RoomPlayer.prefab
deleted file mode 100644
index 2e75f0e..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/RoomPlayer.prefab
+++ /dev/null
@@ -1,67 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &1588750985201798
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 4817109203880908}
- - component: {fileID: 114387717104821018}
- - component: {fileID: 114033720796874720}
- m_Layer: 0
- m_Name: RoomPlayer
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &4817109203880908
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1588750985201798}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &114387717104821018
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1588750985201798}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 0
- m_AssetId: deae2134a1d77704b9c595efe69767dd
- m_SceneId: 0
---- !u!114 &114033720796874720
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1588750985201798}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41fc608223969754e817c29908fdb1d3, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- showRoomGUI: 1
- readyToBegin: 0
- index: 0
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/RoomPlayer.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/RoomPlayer.prefab.meta
deleted file mode 100644
index 153c825..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Prefabs/RoomPlayer.prefab.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: deae2134a1d77704b9c595efe69767dd
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 100100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/README.md b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/README.md
deleted file mode 100644
index 739338b..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/README.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Room Example
-
-In Build Settings, remove all scenes and add all of the scenes from the Examples\Room\Scenes folder in the following order:
-- Offline
-- Room
-- Online
-
-If you opened the Room scene before doing the above steps, you may have to reassign the scenes to the NetworkRoomManagerExt component of the RoomManager scene object.
-
-** Do not assign anything to the Online scene field!** If you do, the room will be bypassed. Assign **only* the Offline and Room and Gameplay scene fields in the inspector.
-
-File -> Build and Run
-
-Start up to 4 built instances: These will all be client players.
-
-Open the Offline scene in the Editor and press Play
-
-Click the Join Game and LAN Host in the editor: This will be host and the 5th player. You can also use LAN Server if you prefer.
-
-Click Join Game and LAN Client in the built instances.
-
-Click Ready in each instance, and finally in the Editor (Host).
-
-Click the Start Game button when all players are ready.
-
-You should now be in the Online scene with your players of random color.
-
-WASDQE keys to move & turn your player capsule.
-Collide with the spheres to score points.
-Lighter colors score higher.
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/README.md.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/README.md.meta
deleted file mode 100644
index eb4961d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/README.md.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 9110f04bd1e8468479f6625342d311c5
-TextScriptImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes.meta
deleted file mode 100644
index 17072cf..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 4f704ae4b4f98ae41a0bce26658850c1
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OfflineScene.unity b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OfflineScene.unity
deleted file mode 100644
index b536b68..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OfflineScene.unity
+++ /dev/null
@@ -1,210 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!29 &1
-OcclusionCullingSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_OcclusionBakeSettings:
- smallestOccluder: 5
- smallestHole: 0.25
- backfaceThreshold: 100
- m_SceneGUID: 00000000000000000000000000000000
- m_OcclusionCullingData: {fileID: 0}
---- !u!104 &2
-RenderSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 9
- m_Fog: 0
- m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
- m_FogMode: 3
- m_FogDensity: 0.01
- m_LinearFogStart: 0
- m_LinearFogEnd: 300
- m_AmbientSkyColor: {r: 0, g: 0, b: 0, a: 1}
- m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
- m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
- m_AmbientIntensity: 1
- m_AmbientMode: 0
- m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
- m_SkyboxMaterial: {fileID: 0}
- m_HaloStrength: 0.5
- m_FlareStrength: 1
- m_FlareFadeSpeed: 3
- m_HaloTexture: {fileID: 0}
- m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
- m_DefaultReflectionMode: 0
- m_DefaultReflectionResolution: 128
- m_ReflectionBounces: 1
- m_ReflectionIntensity: 1
- m_CustomReflection: {fileID: 0}
- m_Sun: {fileID: 0}
- m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
- m_UseRadianceAmbientProbe: 0
---- !u!157 &3
-LightmapSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 11
- m_GIWorkflowMode: 0
- m_GISettings:
- serializedVersion: 2
- m_BounceScale: 1
- m_IndirectOutputScale: 1
- m_AlbedoBoost: 1
- m_EnvironmentLightingMode: 0
- m_EnableBakedLightmaps: 0
- m_EnableRealtimeLightmaps: 0
- m_LightmapEditorSettings:
- serializedVersion: 10
- m_Resolution: 2
- m_BakeResolution: 40
- m_AtlasSize: 1024
- m_AO: 0
- m_AOMaxDistance: 1
- m_CompAOExponent: 1
- m_CompAOExponentDirect: 0
- m_Padding: 2
- m_LightmapParameters: {fileID: 0}
- m_LightmapsBakeMode: 1
- m_TextureCompression: 1
- m_FinalGather: 0
- m_FinalGatherFiltering: 1
- m_FinalGatherRayCount: 256
- m_ReflectionCompression: 2
- m_MixedBakeMode: 2
- m_BakeBackend: 1
- m_PVRSampling: 1
- m_PVRDirectSampleCount: 32
- m_PVRSampleCount: 500
- m_PVRBounces: 2
- m_PVRFilterTypeDirect: 0
- m_PVRFilterTypeIndirect: 0
- m_PVRFilterTypeAO: 0
- m_PVRFilteringMode: 1
- m_PVRCulling: 1
- m_PVRFilteringGaussRadiusDirect: 1
- m_PVRFilteringGaussRadiusIndirect: 5
- m_PVRFilteringGaussRadiusAO: 2
- m_PVRFilteringAtrousPositionSigmaDirect: 0.5
- m_PVRFilteringAtrousPositionSigmaIndirect: 2
- m_PVRFilteringAtrousPositionSigmaAO: 1
- m_ShowResolutionOverlay: 1
- m_LightingDataAsset: {fileID: 0}
- m_UseShadowmask: 1
---- !u!196 &4
-NavMeshSettings:
- serializedVersion: 2
- m_ObjectHideFlags: 0
- m_BuildSettings:
- serializedVersion: 2
- agentTypeID: 0
- agentRadius: 0.5
- agentHeight: 2
- agentSlope: 45
- agentClimb: 0.4
- ledgeDropHeight: 0
- maxJumpAcrossDistance: 0
- minRegionArea: 2
- manualCellSize: 0
- cellSize: 0.16666667
- manualTileSize: 0
- tileSize: 256
- accuratePlacement: 0
- debug:
- m_Flags: 0
- m_NavMeshData: {fileID: 0}
---- !u!1 &639890310
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 639890313}
- - component: {fileID: 639890312}
- - component: {fileID: 639890311}
- - component: {fileID: 639890314}
- m_Layer: 0
- m_Name: Main Camera
- m_TagString: MainCamera
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!81 &639890311
-AudioListener:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 639890310}
- m_Enabled: 1
---- !u!20 &639890312
-Camera:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 639890310}
- m_Enabled: 1
- serializedVersion: 2
- m_ClearFlags: 1
- m_BackGroundColor: {r: 0.23429157, g: 0.254717, b: 0.23546094, a: 0}
- m_projectionMatrixMode: 1
- m_SensorSize: {x: 36, y: 24}
- m_LensShift: {x: 0, y: 0}
- m_GateFitMode: 2
- m_FocalLength: 50
- m_NormalizedViewPortRect:
- serializedVersion: 2
- x: 0
- y: 0
- width: 1
- height: 1
- near clip plane: 0.3
- far clip plane: 1000
- field of view: 60
- orthographic: 0
- orthographic size: 5
- m_Depth: -1
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_RenderingPath: -1
- m_TargetTexture: {fileID: 0}
- m_TargetDisplay: 0
- m_TargetEye: 3
- m_HDR: 1
- m_AllowMSAA: 1
- m_AllowDynamicResolution: 0
- m_ForceIntoRT: 0
- m_OcclusionCulling: 1
- m_StereoConvergence: 10
- m_StereoSeparation: 0.022
---- !u!4 &639890313
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 639890310}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1, z: -10}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &639890314
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 639890310}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 039bde4e5e3b63e46be9b967d06e5469, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- RoomScene: RoomScene
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OfflineScene.unity.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OfflineScene.unity.meta
deleted file mode 100644
index 45332ad..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OfflineScene.unity.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 9e6f14982412b2545a0911ebaaa46a23
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OnlineScene.unity b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OnlineScene.unity
deleted file mode 100644
index 764d6af..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OnlineScene.unity
+++ /dev/null
@@ -1,860 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!29 &1
-OcclusionCullingSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_OcclusionBakeSettings:
- smallestOccluder: 5
- smallestHole: 0.25
- backfaceThreshold: 100
- m_SceneGUID: 00000000000000000000000000000000
- m_OcclusionCullingData: {fileID: 0}
---- !u!104 &2
-RenderSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 9
- m_Fog: 0
- m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
- m_FogMode: 3
- m_FogDensity: 0.01
- m_LinearFogStart: 0
- m_LinearFogEnd: 300
- m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
- m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
- m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
- m_AmbientIntensity: 1
- m_AmbientMode: 0
- m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
- m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
- m_HaloStrength: 0.5
- m_FlareStrength: 1
- m_FlareFadeSpeed: 3
- m_HaloTexture: {fileID: 0}
- m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
- m_DefaultReflectionMode: 0
- m_DefaultReflectionResolution: 128
- m_ReflectionBounces: 1
- m_ReflectionIntensity: 1
- m_CustomReflection: {fileID: 0}
- m_Sun: {fileID: 0}
- m_IndirectSpecularColor: {r: 0.4366757, g: 0.48427194, b: 0.5645252, a: 1}
- m_UseRadianceAmbientProbe: 0
---- !u!157 &3
-LightmapSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 11
- m_GIWorkflowMode: 0
- m_GISettings:
- serializedVersion: 2
- m_BounceScale: 1
- m_IndirectOutputScale: 1
- m_AlbedoBoost: 1
- m_EnvironmentLightingMode: 0
- m_EnableBakedLightmaps: 0
- m_EnableRealtimeLightmaps: 0
- m_LightmapEditorSettings:
- serializedVersion: 10
- m_Resolution: 2
- m_BakeResolution: 40
- m_AtlasSize: 1024
- m_AO: 0
- m_AOMaxDistance: 1
- m_CompAOExponent: 1
- m_CompAOExponentDirect: 0
- m_Padding: 2
- m_LightmapParameters: {fileID: 0}
- m_LightmapsBakeMode: 1
- m_TextureCompression: 1
- m_FinalGather: 0
- m_FinalGatherFiltering: 1
- m_FinalGatherRayCount: 256
- m_ReflectionCompression: 2
- m_MixedBakeMode: 2
- m_BakeBackend: 1
- m_PVRSampling: 1
- m_PVRDirectSampleCount: 32
- m_PVRSampleCount: 500
- m_PVRBounces: 2
- m_PVRFilterTypeDirect: 0
- m_PVRFilterTypeIndirect: 0
- m_PVRFilterTypeAO: 0
- m_PVRFilteringMode: 1
- m_PVRCulling: 1
- m_PVRFilteringGaussRadiusDirect: 1
- m_PVRFilteringGaussRadiusIndirect: 5
- m_PVRFilteringGaussRadiusAO: 2
- m_PVRFilteringAtrousPositionSigmaDirect: 0.5
- m_PVRFilteringAtrousPositionSigmaIndirect: 2
- m_PVRFilteringAtrousPositionSigmaAO: 1
- m_ShowResolutionOverlay: 1
- m_LightingDataAsset: {fileID: 112000002, guid: 83612f89e0d5b404fbd99891bda78df4,
- type: 2}
- m_UseShadowmask: 1
---- !u!196 &4
-NavMeshSettings:
- serializedVersion: 2
- m_ObjectHideFlags: 0
- m_BuildSettings:
- serializedVersion: 2
- agentTypeID: 0
- agentRadius: 0.5
- agentHeight: 2
- agentSlope: 45
- agentClimb: 0.4
- ledgeDropHeight: 0
- maxJumpAcrossDistance: 0
- minRegionArea: 2
- manualCellSize: 0
- cellSize: 0.16666667
- manualTileSize: 0
- tileSize: 256
- accuratePlacement: 0
- debug:
- m_Flags: 0
- m_NavMeshData: {fileID: 0}
---- !u!1 &29930032
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 29930035}
- - component: {fileID: 29930034}
- - component: {fileID: 29930033}
- m_Layer: 0
- m_Name: Spawner
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!114 &29930033
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 29930032}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 1
- localPlayerAuthority: 0
- m_AssetId:
- m_SceneId: 6047645
---- !u!114 &29930034
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 29930032}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 0bf5c082d04f7ea459fcd30e60b5bd70, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- prizePrefab: {fileID: 114251241889735402, guid: 52f1c9ea06cfd154cb68ff9d1b66fc13,
- type: 3}
---- !u!4 &29930035
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 29930032}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &151116940
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 151116942}
- - component: {fileID: 151116941}
- m_Layer: 0
- m_Name: Directional Light
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!108 &151116941
-Light:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 151116940}
- m_Enabled: 1
- serializedVersion: 8
- m_Type: 1
- m_Color: {r: 0.990566, g: 0.9496818, b: 0.82702917, a: 1}
- m_Intensity: 1
- m_Range: 10
- m_SpotAngle: 30
- m_CookieSize: 10
- m_Shadows:
- m_Type: 2
- m_Resolution: -1
- m_CustomResolution: -1
- m_Strength: 0.7
- m_Bias: 0.05
- m_NormalBias: 0.4
- m_NearPlane: 0.2
- m_Cookie: {fileID: 0}
- m_DrawHalo: 0
- m_Flare: {fileID: 0}
- m_RenderMode: 0
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_Lightmapping: 4
- m_LightShadowCasterMode: 0
- m_AreaSize: {x: 1, y: 1}
- m_BounceIntensity: 1
- m_ColorTemperature: 6570
- m_UseColorTemperature: 0
- m_ShadowRadius: 0
- m_ShadowAngle: 0
---- !u!4 &151116942
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 151116940}
- m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
- m_LocalPosition: {x: 0, y: 10, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
---- !u!1 &204334129
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 204334130}
- - component: {fileID: 204334131}
- m_Layer: 0
- m_Name: PlayerStart
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &204334130
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 204334129}
- m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: -15}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1445635740}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &204334131
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 204334129}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &263230754
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 263230755}
- - component: {fileID: 263230756}
- m_Layer: 0
- m_Name: PlayerStart
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &263230755
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 263230754}
- m_LocalRotation: {x: 0, y: 0.38268343, z: 0, w: 0.92387956}
- m_LocalPosition: {x: -15, y: 0, z: -15}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1445635740}
- m_RootOrder: 5
- m_LocalEulerAnglesHint: {x: 0, y: 45, z: 0}
---- !u!114 &263230756
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 263230754}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &290557149
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 290557150}
- - component: {fileID: 290557151}
- m_Layer: 0
- m_Name: PlayerStart
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &290557150
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 290557149}
- m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068}
- m_LocalPosition: {x: -15, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1445635740}
- m_RootOrder: 6
- m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0}
---- !u!114 &290557151
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 290557149}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &733367779
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 733367780}
- - component: {fileID: 733367781}
- m_Layer: 0
- m_Name: PlayerStart
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &733367780
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 733367779}
- m_LocalRotation: {x: -0, y: 1, z: -0, w: 0}
- m_LocalPosition: {x: 0, y: 0, z: 15}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1445635740}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0}
---- !u!114 &733367781
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 733367779}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &990635329
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 990635330}
- - component: {fileID: 990635331}
- m_Layer: 0
- m_Name: PlayerStart
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &990635330
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 990635329}
- m_LocalRotation: {x: 0, y: 0.92387956, z: 0, w: 0.38268343}
- m_LocalPosition: {x: -15, y: 0, z: 15}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1445635740}
- m_RootOrder: 7
- m_LocalEulerAnglesHint: {x: 0, y: 135, z: 0}
---- !u!114 &990635331
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 990635329}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &1050066542
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1050066545}
- - component: {fileID: 1050066544}
- - component: {fileID: 1050066543}
- m_Layer: 0
- m_Name: Main Camera
- m_TagString: MainCamera
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!81 &1050066543
-AudioListener:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1050066542}
- m_Enabled: 1
---- !u!20 &1050066544
-Camera:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1050066542}
- m_Enabled: 1
- serializedVersion: 2
- m_ClearFlags: 1
- m_BackGroundColor: {r: 0.23429157, g: 0.254717, b: 0.23546094, a: 0}
- m_projectionMatrixMode: 1
- m_SensorSize: {x: 36, y: 24}
- m_LensShift: {x: 0, y: 0}
- m_GateFitMode: 2
- m_FocalLength: 50
- m_NormalizedViewPortRect:
- serializedVersion: 2
- x: 0
- y: 0
- width: 1
- height: 1
- near clip plane: 0.3
- far clip plane: 1000
- field of view: 60
- orthographic: 0
- orthographic size: 5
- m_Depth: -1
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_RenderingPath: -1
- m_TargetTexture: {fileID: 0}
- m_TargetDisplay: 0
- m_TargetEye: 3
- m_HDR: 1
- m_AllowMSAA: 1
- m_AllowDynamicResolution: 0
- m_ForceIntoRT: 0
- m_OcclusionCulling: 1
- m_StereoConvergence: 10
- m_StereoSeparation: 0.022
---- !u!4 &1050066545
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1050066542}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 2, z: -10}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1305256737
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1305256745}
- - component: {fileID: 1305256744}
- - component: {fileID: 1305256742}
- - component: {fileID: 1305256743}
- - component: {fileID: 1305256741}
- - component: {fileID: 1305256740}
- - component: {fileID: 1305256739}
- - component: {fileID: 1305256738}
- m_Layer: 0
- m_Name: PlayArea
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!65 &1305256738
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1305256737}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Size: {x: 10, y: 2, z: 0.1}
- m_Center: {x: 0, y: 1, z: 5}
---- !u!65 &1305256739
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1305256737}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Size: {x: 10, y: 2, z: 0.1}
- m_Center: {x: 0, y: 1, z: -5}
---- !u!65 &1305256740
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1305256737}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Size: {x: 0.1, y: 2, z: 10}
- m_Center: {x: 5, y: 1, z: 0}
---- !u!65 &1305256741
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1305256737}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 2
- m_Size: {x: 0.1, y: 2, z: 10}
- m_Center: {x: -5, y: 1, z: 0}
---- !u!23 &1305256742
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1305256737}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 4294967295
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 3201636fa507dad448e9a36d66a80825, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 1
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!64 &1305256743
-MeshCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1305256737}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 3
- m_Convex: 0
- m_CookingOptions: 14
- m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
---- !u!33 &1305256744
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1305256737}
- m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
---- !u!4 &1305256745
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1305256737}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 4, y: 1, z: 4}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1445635739
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1445635740}
- m_Layer: 0
- m_Name: StartPositions
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1445635740
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1445635739}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1.08, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 733367780}
- - {fileID: 2127619492}
- - {fileID: 1975674813}
- - {fileID: 1760045337}
- - {fileID: 204334130}
- - {fileID: 263230755}
- - {fileID: 290557150}
- - {fileID: 990635330}
- m_Father: {fileID: 0}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1760045336
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1760045337}
- - component: {fileID: 1760045338}
- m_Layer: 0
- m_Name: PlayerStart
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1760045337
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1760045336}
- m_LocalRotation: {x: 0, y: 0.3826836, z: -0, w: -0.92387944}
- m_LocalPosition: {x: 15, y: 0, z: -15}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1445635740}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 315, z: 0}
---- !u!114 &1760045338
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1760045336}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &1975674812
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1975674813}
- - component: {fileID: 1975674814}
- m_Layer: 0
- m_Name: PlayerStart
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1975674813
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1975674812}
- m_LocalRotation: {x: 0, y: 0.7071068, z: -0, w: -0.7071068}
- m_LocalPosition: {x: 15, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1445635740}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 270, z: 0}
---- !u!114 &1975674814
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1975674812}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &2127619491
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 2127619492}
- - component: {fileID: 2127619493}
- m_Layer: 0
- m_Name: PlayerStart
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &2127619492
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2127619491}
- m_LocalRotation: {x: 0, y: 0.9238796, z: -0, w: -0.38268325}
- m_LocalPosition: {x: 15, y: 0, z: 15}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 1445635740}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 225, z: 0}
---- !u!114 &2127619493
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2127619491}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OnlineScene.unity.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OnlineScene.unity.meta
deleted file mode 100644
index 8a990fe..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/OnlineScene.unity.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: d7a6763559b31854586c9e49916273ef
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/RoomScene.unity b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/RoomScene.unity
deleted file mode 100644
index 6e3c210..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/RoomScene.unity
+++ /dev/null
@@ -1,321 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!29 &1
-OcclusionCullingSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_OcclusionBakeSettings:
- smallestOccluder: 5
- smallestHole: 0.25
- backfaceThreshold: 100
- m_SceneGUID: 00000000000000000000000000000000
- m_OcclusionCullingData: {fileID: 0}
---- !u!104 &2
-RenderSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 9
- m_Fog: 0
- m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
- m_FogMode: 3
- m_FogDensity: 0.01
- m_LinearFogStart: 0
- m_LinearFogEnd: 300
- m_AmbientSkyColor: {r: 0, g: 0, b: 0, a: 1}
- m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
- m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
- m_AmbientIntensity: 1
- m_AmbientMode: 0
- m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
- m_SkyboxMaterial: {fileID: 0}
- m_HaloStrength: 0.5
- m_FlareStrength: 1
- m_FlareFadeSpeed: 3
- m_HaloTexture: {fileID: 0}
- m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
- m_DefaultReflectionMode: 0
- m_DefaultReflectionResolution: 128
- m_ReflectionBounces: 1
- m_ReflectionIntensity: 1
- m_CustomReflection: {fileID: 0}
- m_Sun: {fileID: 0}
- m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
- m_UseRadianceAmbientProbe: 0
---- !u!157 &3
-LightmapSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 11
- m_GIWorkflowMode: 0
- m_GISettings:
- serializedVersion: 2
- m_BounceScale: 1
- m_IndirectOutputScale: 1
- m_AlbedoBoost: 1
- m_EnvironmentLightingMode: 0
- m_EnableBakedLightmaps: 0
- m_EnableRealtimeLightmaps: 0
- m_LightmapEditorSettings:
- serializedVersion: 10
- m_Resolution: 2
- m_BakeResolution: 40
- m_AtlasSize: 1024
- m_AO: 0
- m_AOMaxDistance: 1
- m_CompAOExponent: 1
- m_CompAOExponentDirect: 0
- m_Padding: 2
- m_LightmapParameters: {fileID: 0}
- m_LightmapsBakeMode: 1
- m_TextureCompression: 1
- m_FinalGather: 0
- m_FinalGatherFiltering: 1
- m_FinalGatherRayCount: 256
- m_ReflectionCompression: 2
- m_MixedBakeMode: 2
- m_BakeBackend: 1
- m_PVRSampling: 1
- m_PVRDirectSampleCount: 32
- m_PVRSampleCount: 500
- m_PVRBounces: 2
- m_PVRFilterTypeDirect: 0
- m_PVRFilterTypeIndirect: 0
- m_PVRFilterTypeAO: 0
- m_PVRFilteringMode: 1
- m_PVRCulling: 1
- m_PVRFilteringGaussRadiusDirect: 1
- m_PVRFilteringGaussRadiusIndirect: 5
- m_PVRFilteringGaussRadiusAO: 2
- m_PVRFilteringAtrousPositionSigmaDirect: 0.5
- m_PVRFilteringAtrousPositionSigmaIndirect: 2
- m_PVRFilteringAtrousPositionSigmaAO: 1
- m_ShowResolutionOverlay: 1
- m_LightingDataAsset: {fileID: 0}
- m_UseShadowmask: 1
---- !u!196 &4
-NavMeshSettings:
- serializedVersion: 2
- m_ObjectHideFlags: 0
- m_BuildSettings:
- serializedVersion: 2
- agentTypeID: 0
- agentRadius: 0.5
- agentHeight: 2
- agentSlope: 45
- agentClimb: 0.4
- ledgeDropHeight: 0
- maxJumpAcrossDistance: 0
- minRegionArea: 2
- manualCellSize: 0
- cellSize: 0.16666667
- manualTileSize: 0
- tileSize: 256
- accuratePlacement: 0
- debug:
- m_Flags: 0
- m_NavMeshData: {fileID: 0}
---- !u!1 &639890310
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 639890313}
- - component: {fileID: 639890312}
- - component: {fileID: 639890311}
- m_Layer: 0
- m_Name: Main Camera
- m_TagString: MainCamera
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!81 &639890311
-AudioListener:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 639890310}
- m_Enabled: 1
---- !u!20 &639890312
-Camera:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 639890310}
- m_Enabled: 1
- serializedVersion: 2
- m_ClearFlags: 1
- m_BackGroundColor: {r: 0.23429157, g: 0.254717, b: 0.23546094, a: 0}
- m_projectionMatrixMode: 1
- m_SensorSize: {x: 36, y: 24}
- m_LensShift: {x: 0, y: 0}
- m_GateFitMode: 2
- m_FocalLength: 50
- m_NormalizedViewPortRect:
- serializedVersion: 2
- x: 0
- y: 0
- width: 1
- height: 1
- near clip plane: 0.3
- far clip plane: 1000
- field of view: 60
- orthographic: 0
- orthographic size: 5
- m_Depth: -1
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_RenderingPath: 3
- m_TargetTexture: {fileID: 0}
- m_TargetDisplay: 0
- m_TargetEye: 3
- m_HDR: 1
- m_AllowMSAA: 0
- m_AllowDynamicResolution: 0
- m_ForceIntoRT: 0
- m_OcclusionCulling: 1
- m_StereoConvergence: 10
- m_StereoSeparation: 0.022
---- !u!4 &639890313
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 639890310}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1, z: -10}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &2008127829
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 2008127832}
- - component: {fileID: 2008127833}
- - component: {fileID: 2008127831}
- - component: {fileID: 2008127830}
- m_Layer: 0
- m_Name: RoomManager
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!114 &2008127830
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2008127829}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- OnClientConnected:
- m_PersistentCalls:
- m_Calls: []
- OnClientDataReceived:
- m_PersistentCalls:
- m_Calls: []
- OnClientError:
- m_PersistentCalls:
- m_Calls: []
- OnClientDisconnected:
- m_PersistentCalls:
- m_Calls: []
- OnServerConnected:
- m_PersistentCalls:
- m_Calls: []
- OnServerDataReceived:
- m_PersistentCalls:
- m_Calls: []
- OnServerError:
- m_PersistentCalls:
- m_Calls: []
- OnServerDisconnected:
- m_PersistentCalls:
- m_Calls: []
- port: 7780
- NoDelay: 1
- serverMaxMessageSize: 16384
- clientMaxMessageSize: 16384
---- !u!114 &2008127831
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2008127829}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: e7d8650c751710349bb9546d1697b9cb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- dontDestroyOnLoad: 1
- runInBackground: 1
- startOnHeadless: 1
- serverTickRate: 30
- showDebugMessages: 0
- offlineScene: OfflineScene
- onlineScene:
- transport: {fileID: 2008127830}
- networkAddress: localhost
- maxConnections: 5
- authenticator: {fileID: 0}
- playerPrefab: {fileID: 1480027675339556, guid: 21daf89214c6ee443ad6875b73083c60,
- type: 3}
- autoCreatePlayer: 1
- playerSpawnMethod: 1
- spawnPrefabs:
- - {fileID: 1139254171913846, guid: 52f1c9ea06cfd154cb68ff9d1b66fc13, type: 3}
- showRoomGUI: 1
- minPlayers: 1
- roomPlayerPrefab: {fileID: 114033720796874720, guid: deae2134a1d77704b9c595efe69767dd,
- type: 3}
- RoomScene: RoomScene
- GameplayScene: OnlineScene
- roomSlots: []
- allPlayersReady: 0
---- !u!4 &2008127832
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2008127829}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &2008127833
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2008127829}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 6442dc8070ceb41f094e44de0bf87274, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- showGUI: 1
- offsetX: 0
- offsetY: 0
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/RoomScene.unity.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/RoomScene.unity.meta
deleted file mode 100644
index 8749026..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scenes/RoomScene.unity.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 48478f4d522f96945b8396f376299d3a
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts.meta
deleted file mode 100644
index b15256a..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 03401915dd450454e88f0a839d3346f1
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomManagerExt.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomManagerExt.cs
deleted file mode 100644
index 69fea5c..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomManagerExt.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using UnityEngine;
-using UnityEngine.Rendering;
-
-namespace Mirror.Examples.NetworkRoom
-{
- [AddComponentMenu("")]
- public class NetworkRoomManagerExt : NetworkRoomManager
- {
- ///
- /// Called just after GamePlayer object is instantiated and just before it replaces RoomPlayer object.
- /// This is the ideal point to pass any data like player name, credentials, tokens, colors, etc.
- /// into the GamePlayer object as it is about to enter the Online scene.
- ///
- ///
- ///
- /// true unless some code in here decides it needs to abort the replacement
- public override bool OnRoomServerSceneLoadedForPlayer(GameObject roomPlayer, GameObject gamePlayer)
- {
- PlayerController player = gamePlayer.GetComponent();
- player.index = roomPlayer.GetComponent().index;
- player.playerColor = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);
- return true;
- }
-
- /*
- This code below is to demonstrate how to do a Start button that only appears for the Host player
- showStartButton is a local bool that's needed because OnRoomServerPlayersReady is only fired when
- all players are ready, but if a player cancels their ready state there's no callback to set it back to false
- Therefore, allPlayersReady is used in combination with showStartButton to show/hide the Start button correctly.
- Setting showStartButton false when the button is pressed hides it in the game scene since NetworkRoomManager
- is set as DontDestroyOnLoad = true.
- */
-
- bool showStartButton;
-
- public override void OnRoomServerPlayersReady()
- {
- // calling the base method calls ServerChangeScene as soon as all players are in Ready state.
- if (isHeadless)
- base.OnRoomServerPlayersReady();
- else
- showStartButton = true;
- }
-
- public override void OnGUI()
- {
- base.OnGUI();
-
- if (allPlayersReady && showStartButton && GUI.Button(new Rect(150, 300, 120, 20), "START GAME"))
- {
- // set to false to hide it in the game scene
- showStartButton = false;
-
- ServerChangeScene(GameplayScene);
- }
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomManagerExt.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomManagerExt.cs.meta
deleted file mode 100644
index d8f5760..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomManagerExt.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: e7d8650c751710349bb9546d1697b9cb
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomPlayerExt.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomPlayerExt.cs
deleted file mode 100644
index aa981ce..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomPlayerExt.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using UnityEngine;
-using UnityEngine.SceneManagement;
-
-namespace Mirror.Examples.NetworkRoom
-{
- [AddComponentMenu("")]
- public class NetworkRoomPlayerExt : NetworkRoomPlayer
- {
- public override void OnStartClient()
- {
- if (LogFilter.Debug) Debug.LogFormat("OnStartClient {0}", SceneManager.GetActiveScene().name);
-
- base.OnStartClient();
- }
-
- public override void OnClientEnterRoom()
- {
- if (LogFilter.Debug) Debug.LogFormat("OnClientEnterRoom {0}", SceneManager.GetActiveScene().name);
- }
-
- public override void OnClientExitRoom()
- {
- if (LogFilter.Debug) Debug.LogFormat("OnClientExitRoom {0}", SceneManager.GetActiveScene().name);
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomPlayerExt.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomPlayerExt.cs.meta
deleted file mode 100644
index 8e4d135..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/NetworkRoomPlayerExt.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 41fc608223969754e817c29908fdb1d3
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/OfflineGUI.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/OfflineGUI.cs
deleted file mode 100644
index 12c3d9b..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/OfflineGUI.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using UnityEngine;
-using UnityEngine.SceneManagement;
-
-namespace Mirror.Examples.NetworkRoom
-{
- public class OfflineGUI : MonoBehaviour
- {
- [Scene]
- public string RoomScene;
-
- void Start()
- {
- // Ensure main camera is enabled because it will be disabled by PlayerController
- Camera.main.enabled = true;
- }
-
- void OnGUI()
- {
- GUILayout.BeginArea(new Rect(10, 10, 200, 130));
-
- GUILayout.Box("OFFLINE SCENE");
- GUILayout.Box("WASDQE keys to move & turn\nTouch the spheres for points\nLighter colors score higher");
-
- if (GUILayout.Button("Join Game"))
- SceneManager.LoadScene(RoomScene);
-
- GUILayout.EndArea();
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/OfflineGUI.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/OfflineGUI.cs.meta
deleted file mode 100644
index 89237e0..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/OfflineGUI.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 039bde4e5e3b63e46be9b967d06e5469
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/PlayerController.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/PlayerController.cs
deleted file mode 100644
index 9ebfbb6..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/PlayerController.cs
+++ /dev/null
@@ -1,158 +0,0 @@
-using UnityEngine;
-
-namespace Mirror.Examples.NetworkRoom
-{
- [RequireComponent(typeof(CharacterController))]
- public class PlayerController : NetworkBehaviour
- {
- [SyncVar]
- public int index;
-
- [SyncVar]
- public uint score;
-
- [SyncVar(hook = nameof(SetColor))]
- public Color playerColor = Color.black;
-
- // Unity clones the material when GetComponent().material is called
- // Cache it here and destroy it in OnDestroy to prevent a memory leak
- Material cachedMaterial;
-
- void SetColor(Color color)
- {
- if (cachedMaterial == null) cachedMaterial = GetComponent().material;
- cachedMaterial.color = color;
- }
-
- void OnDisable()
- {
- if (isLocalPlayer)
- {
- Camera.main.transform.SetParent(null);
- Camera.main.transform.localPosition = new Vector3(0f, 50f, 0f);
- Camera.main.transform.localEulerAngles = new Vector3(90f, 0f, 0f);
- }
- }
-
- void OnDestroy()
- {
- Destroy(cachedMaterial);
- }
-
- CharacterController characterController;
-
- public override void OnStartLocalPlayer()
- {
- base.OnStartLocalPlayer();
-
- characterController = GetComponent();
-
- Camera.main.transform.SetParent(transform);
- Camera.main.transform.localPosition = new Vector3(0f, 3f, -8f);
- Camera.main.transform.localEulerAngles = new Vector3(10f, 0f, 0f);
- }
-
- [Header("Movement Settings")]
- public float moveSpeed = 8f;
- public float turnSpeedAccel = 5f;
- public float turnSpeedDecel = 5f;
- public float maxTurnSpeed = 150f;
-
- [Header("Jump Settings")]
- public float jumpSpeed = 0f;
- public float jumpFactor = .025F;
-
- [Header("Diagnostics")]
- public float horizontal = 0f;
- public float vertical = 0f;
- public float turn = 0f;
- public bool isGrounded = true;
- public bool isFalling = false;
-
- void Update()
- {
- if (!isLocalPlayer) return;
-
- horizontal = Input.GetAxis("Horizontal");
- vertical = Input.GetAxis("Vertical");
-
- if (Input.GetKey(KeyCode.Q) && (turn > -maxTurnSpeed))
- turn -= turnSpeedAccel;
- else if (Input.GetKey(KeyCode.E) && (turn < maxTurnSpeed))
- turn += turnSpeedAccel;
- else if (turn > turnSpeedDecel)
- turn -= turnSpeedDecel;
- else if (turn < -turnSpeedDecel)
- turn += turnSpeedDecel;
- else
- turn = 0f;
-
- if (!isFalling && Input.GetKey(KeyCode.Space) && (isGrounded || jumpSpeed < 1))
- jumpSpeed += jumpFactor;
- else if (isGrounded)
- isFalling = false;
- else
- {
- isFalling = true;
- jumpSpeed = 0;
- }
- }
-
- void FixedUpdate()
- {
- if (!isLocalPlayer || characterController == null) return;
-
- transform.Rotate(0f, turn * Time.fixedDeltaTime, 0f);
-
- Vector3 direction = new Vector3(horizontal, jumpSpeed, vertical);
- direction = Vector3.ClampMagnitude(direction, 1f);
- direction = transform.TransformDirection(direction);
- direction *= moveSpeed;
-
- if (jumpSpeed > 0)
- characterController.Move(direction * Time.fixedDeltaTime);
- else
- characterController.SimpleMove(direction);
-
- isGrounded = characterController.isGrounded;
- }
-
- GameObject controllerColliderHitObject;
-
- void OnControllerColliderHit(ControllerColliderHit hit)
- {
- // If player and prize objects are on their own layer(s) with correct
- // collision matrix, we wouldn't have to validate the hit.gameobject.
- // Since this is just an example, project settings aren't included so we check the name.
-
- controllerColliderHitObject = hit.gameObject;
-
- if (isLocalPlayer && controllerColliderHitObject.name.StartsWith("Prize"))
- {
- if (LogFilter.Debug) Debug.LogFormat("OnControllerColliderHit {0}[{1}] with {2}[{3}]", name, netId, controllerColliderHitObject.name, controllerColliderHitObject.GetComponent().netId);
-
- // Disable the prize gameobject so it doesn't impede player movement
- // It's going to be destroyed in a few frames and we don't want to spam CmdClaimPrize.
- // OnControllerColliderHit will fire many times as the player slides against the object.
- controllerColliderHitObject.SetActive(false);
-
- CmdClaimPrize(controllerColliderHitObject);
- }
- }
-
- [Command]
- void CmdClaimPrize(GameObject hitObject)
- {
- // Null check is required, otherwise close timing of multiple claims could throw a null ref.
- if (hitObject != null)
- {
- hitObject.GetComponent().ClaimPrize(gameObject);
- }
- }
-
- void OnGUI()
- {
- GUI.Box(new Rect(10f + (index * 110), 10f, 100f, 25f), score.ToString().PadLeft(10));
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/PlayerController.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/PlayerController.cs.meta
deleted file mode 100644
index 74f8f95..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/PlayerController.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 24fd13686a451ad498101a604d134e39
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Reward.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Reward.cs
deleted file mode 100644
index aefab97..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Reward.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using UnityEngine;
-
-namespace Mirror.Examples.NetworkRoom
-{
- public class Reward : NetworkBehaviour
- {
- [SyncVar(hook = nameof(SetColor))]
- public Color prizeColor = Color.black;
-
- // Unity makes a clone of the material when GetComponent().material is used
- // Cache it here and Destroy it in OnDestroy to prevent a memory leak
- Material materialClone;
-
- void SetColor(Color color)
- {
- if (materialClone == null) materialClone = GetComponent().material;
- materialClone.color = color;
- }
-
- void OnDestroy()
- {
- Destroy(materialClone);
- }
-
- public bool available = true;
- public Spawner spawner;
- uint points;
-
- // This is called from PlayerController.CmdClaimPrize which is invoked by PlayerController.OnControllerColliderHit
- // This only runs on the server
- public void ClaimPrize(GameObject player)
- {
- if (available)
- {
- // This is a fast switch to prevent two players claiming the prize in a bang-bang close contest for it.
- // First hit turns it off, pending the object being destroyed a few frames later.
- available = false;
-
- // calculate the points from the color ... lighter scores higher as the average approaches 255
- // UnityEngine.Color RGB values are float fractions of 255
- points = (uint)(((prizeColor.r * 255) + (prizeColor.g * 255) + (prizeColor.b * 255)) / 3);
- if (LogFilter.Debug) Debug.LogFormat("Scored {0} points R:{1} G:{2} B:{3}", points, prizeColor.r, prizeColor.g, prizeColor.b);
-
- // award the points via SyncVar on the PlayerController
- player.GetComponent().score += points;
-
- // spawn a replacement
- spawner.SpawnPrize();
-
- // destroy this one
- NetworkServer.Destroy(gameObject);
- }
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Reward.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Reward.cs.meta
deleted file mode 100644
index 879bc7d..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Reward.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: a22f9eb8ebad79e47babf4c051a714ee
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Spawner.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Spawner.cs
deleted file mode 100644
index ca39186..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Spawner.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using UnityEngine;
-
-namespace Mirror.Examples.NetworkRoom
-{
- public class Spawner : NetworkBehaviour
- {
- public NetworkIdentity prizePrefab;
-
- float x;
- float z;
-
- GameObject newPrize;
- Reward reward;
-
- public override void OnStartServer()
- {
- for (int i = 0; i < 10; i++)
- SpawnPrize();
- }
-
- public void SpawnPrize()
- {
- x = Random.Range(-19, 20);
- z = Random.Range(-19, 20);
-
- newPrize = Instantiate(prizePrefab.gameObject, new Vector3(x, 1, z), Quaternion.identity);
- newPrize.name = prizePrefab.name;
- reward = newPrize.gameObject.GetComponent();
- reward.spawner = this;
- reward.prizeColor = Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);
-
- if (LogFilter.Debug) Debug.LogFormat("Spawning Prize R:{0} G:{1} B:{2}", reward.prizeColor.r, reward.prizeColor.g, reward.prizeColor.b);
-
- NetworkServer.Spawn(newPrize);
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Spawner.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Spawner.cs.meta
deleted file mode 100644
index d4103d6..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Room/Scripts/Spawner.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 0bf5c082d04f7ea459fcd30e60b5bd70
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks.meta
deleted file mode 100644
index bee4222..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: a6dc5104926d44c9296aec7699989ac3
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models.meta
deleted file mode 100644
index c94259a..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 6878aacf12b204d03a94f71e49f9ad60
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank.meta
deleted file mode 100644
index 93b0075..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: d8b3e43538fc240feb28e07816c7e733
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/BaseColor.png b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/BaseColor.png
deleted file mode 100644
index bcd4bee..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/BaseColor.png and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/BaseColor.png.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/BaseColor.png.meta
deleted file mode 100644
index 6e069a1..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/BaseColor.png.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: ce00d67f9368944fa8ef4de6ccc77bfa
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 9
- mipmaps:
- mipMapMode: 0
- enableMipMap: 1
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: 1
- maxTextureSize: 2048
- textureSettings:
- serializedVersion: 2
- filterMode: -1
- aniso: -1
- mipBias: -100
- wrapU: -1
- wrapV: -1
- wrapW: -1
- nPOTScale: 1
- lightmap: 0
- compressionQuality: 50
- spriteMode: 0
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 100
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 0
- spriteTessellationDetail: -1
- textureType: 0
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 2048
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 1
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID:
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Controller.controller b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Controller.controller
deleted file mode 100644
index e05d28c..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Controller.controller
+++ /dev/null
@@ -1,272 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!91 &9100000
-AnimatorController:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Controller
- serializedVersion: 5
- m_AnimatorParameters:
- - m_Name: Moving
- m_Type: 4
- m_DefaultFloat: 0
- m_DefaultInt: 0
- m_DefaultBool: 0
- m_Controller: {fileID: 0}
- - m_Name: Shoot
- m_Type: 9
- m_DefaultFloat: 0
- m_DefaultInt: 0
- m_DefaultBool: 0
- m_Controller: {fileID: 0}
- m_AnimatorLayers:
- - serializedVersion: 5
- m_Name: Base Layer
- m_StateMachine: {fileID: 1107772262116321704}
- m_Mask: {fileID: 0}
- m_Motions: []
- m_Behaviours: []
- m_BlendingMode: 0
- m_SyncedLayerIndex: -1
- m_DefaultWeight: 0
- m_IKPass: 0
- m_SyncedLayerAffectsTiming: 0
- m_Controller: {fileID: 9100000}
---- !u!1101 &1101104249963802978
-AnimatorStateTransition:
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name:
- m_Conditions:
- - m_ConditionMode: 1
- m_ConditionEvent: Moving
- m_EventTreshold: 0
- m_DstStateMachine: {fileID: 0}
- m_DstState: {fileID: 1102824315819425342}
- m_Solo: 0
- m_Mute: 0
- m_IsExit: 0
- serializedVersion: 3
- m_TransitionDuration: 0.25
- m_TransitionOffset: 0
- m_ExitTime: 0.6
- m_HasExitTime: 0
- m_HasFixedDuration: 1
- m_InterruptionSource: 0
- m_OrderedInterruption: 1
- m_CanTransitionToSelf: 1
---- !u!1101 &1101366829127142966
-AnimatorStateTransition:
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name:
- m_Conditions:
- - m_ConditionMode: 1
- m_ConditionEvent: Shoot
- m_EventTreshold: 0
- m_DstStateMachine: {fileID: 0}
- m_DstState: {fileID: 1102254808008813326}
- m_Solo: 0
- m_Mute: 0
- m_IsExit: 0
- serializedVersion: 3
- m_TransitionDuration: 0
- m_TransitionOffset: 0
- m_ExitTime: 1
- m_HasExitTime: 0
- m_HasFixedDuration: 1
- m_InterruptionSource: 0
- m_OrderedInterruption: 1
- m_CanTransitionToSelf: 1
---- !u!1101 &1101806660142692138
-AnimatorStateTransition:
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name:
- m_Conditions:
- - m_ConditionMode: 2
- m_ConditionEvent: Moving
- m_EventTreshold: 0
- m_DstStateMachine: {fileID: 0}
- m_DstState: {fileID: 1102207974245764242}
- m_Solo: 0
- m_Mute: 0
- m_IsExit: 0
- serializedVersion: 3
- m_TransitionDuration: 0.25
- m_TransitionOffset: 0
- m_ExitTime: 0.6
- m_HasExitTime: 0
- m_HasFixedDuration: 1
- m_InterruptionSource: 0
- m_OrderedInterruption: 1
- m_CanTransitionToSelf: 1
---- !u!1101 &1101862483397811748
-AnimatorStateTransition:
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name:
- m_Conditions:
- - m_ConditionMode: 2
- m_ConditionEvent: Moving
- m_EventTreshold: 0
- m_DstStateMachine: {fileID: 0}
- m_DstState: {fileID: 1102207974245764242}
- m_Solo: 0
- m_Mute: 0
- m_IsExit: 0
- serializedVersion: 3
- m_TransitionDuration: 0.25
- m_TransitionOffset: 0
- m_ExitTime: 0.75
- m_HasExitTime: 0
- m_HasFixedDuration: 1
- m_InterruptionSource: 0
- m_OrderedInterruption: 1
- m_CanTransitionToSelf: 1
---- !u!1101 &1101947542735704306
-AnimatorStateTransition:
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name:
- m_Conditions:
- - m_ConditionMode: 1
- m_ConditionEvent: Moving
- m_EventTreshold: 0
- m_DstStateMachine: {fileID: 0}
- m_DstState: {fileID: 1102824315819425342}
- m_Solo: 0
- m_Mute: 0
- m_IsExit: 0
- serializedVersion: 3
- m_TransitionDuration: 0.25
- m_TransitionOffset: 0
- m_ExitTime: 0.75
- m_HasExitTime: 0
- m_HasFixedDuration: 1
- m_InterruptionSource: 0
- m_OrderedInterruption: 1
- m_CanTransitionToSelf: 1
---- !u!1102 &1102207974245764242
-AnimatorState:
- serializedVersion: 5
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Idle
- m_Speed: 1
- m_CycleOffset: 0
- m_Transitions:
- - {fileID: 1101947542735704306}
- m_StateMachineBehaviours: []
- m_Position: {x: 50, y: 50, z: 0}
- m_IKOnFeet: 0
- m_WriteDefaultValues: 1
- m_Mirror: 0
- m_SpeedParameterActive: 0
- m_MirrorParameterActive: 0
- m_CycleOffsetParameterActive: 0
- m_TimeParameterActive: 0
- m_Motion: {fileID: 0}
- m_Tag:
- m_SpeedParameter:
- m_MirrorParameter:
- m_CycleOffsetParameter:
- m_TimeParameter:
---- !u!1102 &1102254808008813326
-AnimatorState:
- serializedVersion: 5
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Shoot
- m_Speed: 1
- m_CycleOffset: 0
- m_Transitions:
- - {fileID: 1101104249963802978}
- - {fileID: 1101806660142692138}
- m_StateMachineBehaviours: []
- m_Position: {x: 50, y: 50, z: 0}
- m_IKOnFeet: 0
- m_WriteDefaultValues: 1
- m_Mirror: 0
- m_SpeedParameterActive: 0
- m_MirrorParameterActive: 0
- m_CycleOffsetParameterActive: 0
- m_TimeParameterActive: 0
- m_Motion: {fileID: 7400006, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- m_Tag:
- m_SpeedParameter:
- m_MirrorParameter:
- m_CycleOffsetParameter:
- m_TimeParameter:
---- !u!1102 &1102824315819425342
-AnimatorState:
- serializedVersion: 5
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Moving
- m_Speed: 1
- m_CycleOffset: 0
- m_Transitions:
- - {fileID: 1101862483397811748}
- m_StateMachineBehaviours: []
- m_Position: {x: 50, y: 50, z: 0}
- m_IKOnFeet: 0
- m_WriteDefaultValues: 1
- m_Mirror: 0
- m_SpeedParameterActive: 0
- m_MirrorParameterActive: 0
- m_CycleOffsetParameterActive: 0
- m_TimeParameterActive: 0
- m_Motion: {fileID: 7400004, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- m_Tag:
- m_SpeedParameter:
- m_MirrorParameter:
- m_CycleOffsetParameter:
- m_TimeParameter:
---- !u!1107 &1107772262116321704
-AnimatorStateMachine:
- serializedVersion: 5
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Base Layer
- m_ChildStates:
- - serializedVersion: 1
- m_State: {fileID: 1102207974245764242}
- m_Position: {x: 252, y: 48, z: 0}
- - serializedVersion: 1
- m_State: {fileID: 1102824315819425342}
- m_Position: {x: 252, y: 204, z: 0}
- - serializedVersion: 1
- m_State: {fileID: 1102254808008813326}
- m_Position: {x: 420, y: 120, z: 0}
- m_ChildStateMachines: []
- m_AnyStateTransitions:
- - {fileID: 1101366829127142966}
- m_EntryTransitions: []
- m_StateMachineTransitions: {}
- m_StateMachineBehaviours: []
- m_AnyStatePosition: {x: 60, y: 132, z: 0}
- m_EntryPosition: {x: 60, y: 168, z: 0}
- m_ExitPosition: {x: 60, y: 96, z: 0}
- m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
- m_DefaultState: {fileID: 1102207974245764242}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Controller.controller.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Controller.controller.meta
deleted file mode 100644
index 7e1061c..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Controller.controller.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: a7211483bbd794b6d85ed88576e7d85c
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 9100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Emissive.png b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Emissive.png
deleted file mode 100644
index 61ca0cb..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Emissive.png and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Emissive.png.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Emissive.png.meta
deleted file mode 100644
index 333174c..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Emissive.png.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: 9b3e91ab0048a4aa3a17706a349c6bf5
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 9
- mipmaps:
- mipMapMode: 0
- enableMipMap: 1
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: 1
- maxTextureSize: 2048
- textureSettings:
- serializedVersion: 2
- filterMode: -1
- aniso: -1
- mipBias: -100
- wrapU: -1
- wrapV: -1
- wrapW: -1
- nPOTScale: 1
- lightmap: 0
- compressionQuality: 50
- spriteMode: 0
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 100
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 0
- spriteTessellationDetail: -1
- textureType: 0
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 2048
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 1
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID:
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Metallic.png b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Metallic.png
deleted file mode 100644
index d5d5559..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Metallic.png and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Metallic.png.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Metallic.png.meta
deleted file mode 100644
index 91006e4..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Metallic.png.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: a7467e18a834e4d1390091c8b1ea562c
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 9
- mipmaps:
- mipMapMode: 0
- enableMipMap: 1
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: 1
- maxTextureSize: 2048
- textureSettings:
- serializedVersion: 2
- filterMode: -1
- aniso: -1
- mipBias: -100
- wrapU: -1
- wrapV: -1
- wrapW: -1
- nPOTScale: 1
- lightmap: 0
- compressionQuality: 50
- spriteMode: 0
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 100
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 0
- spriteTessellationDetail: -1
- textureType: 0
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 2048
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 1
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID:
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Normal.png b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Normal.png
deleted file mode 100644
index f1a448f..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Normal.png and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Normal.png.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Normal.png.meta
deleted file mode 100644
index acc128a..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Normal.png.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: 2617bfecca4d44805a3a51a7aa215d7c
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 9
- mipmaps:
- mipMapMode: 0
- enableMipMap: 1
- sRGBTexture: 0
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: 1
- maxTextureSize: 2048
- textureSettings:
- serializedVersion: 2
- filterMode: -1
- aniso: -1
- mipBias: -100
- wrapU: -1
- wrapV: -1
- wrapW: -1
- nPOTScale: 1
- lightmap: 0
- compressionQuality: 50
- spriteMode: 0
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 100
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 0
- spriteTessellationDetail: -1
- textureType: 1
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 2048
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 1
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID:
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Recon_Tank - License.txt b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Recon_Tank - License.txt
deleted file mode 100644
index ed10006..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Recon_Tank - License.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Recon Tank (update), by Mophs
-https://opengameart.org/users/mophs
-
-Based on original work, Recon Tank, By MNDV.ecb, 2018 Eric Buisson
-https://opengameart.org/content/recon-tank
-
-CC-BY 4.0
\ No newline at end of file
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Recon_Tank - License.txt.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Recon_Tank - License.txt.meta
deleted file mode 100644
index 2168518..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/Recon_Tank - License.txt.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 6e745106dbbc3412bbe43eaf25dabd4f
-TextScriptImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/TankMaterial.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/TankMaterial.mat
deleted file mode 100644
index 207b1f7..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/TankMaterial.mat
+++ /dev/null
@@ -1,82 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: TankMaterial
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords: _EMISSION _METALLICGLOSSMAP _NORMALMAP _SPECGLOSSMAP
- m_LightmapFlags: 0
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 2800000, guid: 2617bfecca4d44805a3a51a7aa215d7c, type: 3}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 2800000, guid: 9b3e91ab0048a4aa3a17706a349c6bf5, type: 3}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 2800000, guid: ce00d67f9368944fa8ef4de6ccc77bfa, type: 3}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 2800000, guid: a7467e18a834e4d1390091c8b1ea562c, type: 3}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _SpecGlossMap:
- m_Texture: {fileID: 2800000, guid: a7467e18a834e4d1390091c8b1ea562c, type: 3}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1.75
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 0.09
- - _Glossiness: 0.5
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 1, g: 1, b: 1, a: 1}
- - _EmissionColor: {r: 1, g: 1, b: 1, a: 1}
- - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/TankMaterial.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/TankMaterial.mat.meta
deleted file mode 100644
index 080f534..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/TankMaterial.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 2e67e42170aa64aa9a33424f8045ac89
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/reconTank.fbx b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/reconTank.fbx
deleted file mode 100644
index 5877b09..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/reconTank.fbx and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/reconTank.fbx.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/reconTank.fbx.meta
deleted file mode 100644
index 1ac1ee0..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Models/(Public Domain) Recon_Tank/reconTank.fbx.meta
+++ /dev/null
@@ -1,239 +0,0 @@
-fileFormatVersion: 2
-guid: 38b49695fc0a4418bbc350f2366660c5
-ModelImporter:
- serializedVersion: 23
- fileIDToRecycleName:
- 100000: Barrel
- 100002: Barrel_end
- 100004: Chasis
- 100006: Recon_Tank
- 100008: Recon_Tank_Rig
- 100010: //RootNode
- 100012: Root
- 100014: Turret
- 100016: Wheel_Front_L
- 100018: Wheel_Front_L_end
- 100020: Wheel_Middle_L
- 100022: Wheel_Middle_L_end
- 100024: Wheel_Rear_L
- 100026: Wheel_Rear_L_end
- 400000: Barrel
- 400002: Barrel_end
- 400004: Chasis
- 400006: Recon_Tank
- 400008: Recon_Tank_Rig
- 400010: //RootNode
- 400012: Root
- 400014: Turret
- 400016: Wheel_Front_L
- 400018: Wheel_Front_L_end
- 400020: Wheel_Middle_L
- 400022: Wheel_Middle_L_end
- 400024: Wheel_Rear_L
- 400026: Wheel_Rear_L_end
- 2100000: Recon_Tank
- 4300000: Recon_Tank
- 7400000: Recon_Tank_Rig|Drive
- 7400002: Recon_Tank_Rig|Forward
- 7400004: Recon_Tank_Rig|Idle
- 7400006: Recon_Tank_Rig|Shoot
- 9500000: //RootNode
- 13700000: Recon_Tank
- externalObjects: {}
- materials:
- importMaterials: 1
- materialName: 0
- materialSearch: 1
- materialLocation: 1
- animations:
- legacyGenerateAnimations: 4
- bakeSimulation: 0
- resampleCurves: 1
- optimizeGameObjects: 0
- motionNodeName:
- rigImportErrors:
- rigImportWarnings:
- animationImportErrors:
- animationImportWarnings:
- animationRetargetingWarnings:
- animationDoRetargetingWarnings: 0
- importAnimatedCustomProperties: 0
- importConstraints: 0
- animationCompression: 1
- animationRotationError: 0.5
- animationPositionError: 0.5
- animationScaleError: 0.5
- animationWrapMode: 0
- extraExposedTransformPaths: []
- extraUserProperties: []
- clipAnimations:
- - serializedVersion: 16
- name: Recon_Tank_Rig|Drive
- takeName: Recon_Tank_Rig|Drive
- firstFrame: 0
- lastFrame: 1
- wrapMode: 0
- orientationOffsetY: 0
- level: 0
- cycleOffset: 0
- loop: 0
- hasAdditiveReferencePose: 0
- loopTime: 0
- loopBlend: 0
- loopBlendOrientation: 0
- loopBlendPositionY: 0
- loopBlendPositionXZ: 0
- keepOriginalOrientation: 0
- keepOriginalPositionY: 1
- keepOriginalPositionXZ: 0
- heightFromFeet: 0
- mirror: 0
- bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
- curves: []
- events: []
- transformMask: []
- maskType: 3
- maskSource: {instanceID: 0}
- additiveReferencePoseFrame: 0
- - serializedVersion: 16
- name: Recon_Tank_Rig|Forward
- takeName: Recon_Tank_Rig|Forward
- firstFrame: 0
- lastFrame: 25
- wrapMode: 0
- orientationOffsetY: 0
- level: 0
- cycleOffset: 0
- loop: 0
- hasAdditiveReferencePose: 0
- loopTime: 0
- loopBlend: 0
- loopBlendOrientation: 0
- loopBlendPositionY: 0
- loopBlendPositionXZ: 0
- keepOriginalOrientation: 0
- keepOriginalPositionY: 1
- keepOriginalPositionXZ: 0
- heightFromFeet: 0
- mirror: 0
- bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
- curves: []
- events: []
- transformMask: []
- maskType: 3
- maskSource: {instanceID: 0}
- additiveReferencePoseFrame: 0
- - serializedVersion: 16
- name: Recon_Tank_Rig|Idle
- takeName: Recon_Tank_Rig|Idle
- firstFrame: 0
- lastFrame: 11
- wrapMode: 0
- orientationOffsetY: 0
- level: 0
- cycleOffset: 0
- loop: 0
- hasAdditiveReferencePose: 0
- loopTime: 1
- loopBlend: 1
- loopBlendOrientation: 0
- loopBlendPositionY: 0
- loopBlendPositionXZ: 0
- keepOriginalOrientation: 0
- keepOriginalPositionY: 1
- keepOriginalPositionXZ: 0
- heightFromFeet: 0
- mirror: 0
- bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
- curves: []
- events: []
- transformMask: []
- maskType: 3
- maskSource: {instanceID: 0}
- additiveReferencePoseFrame: 0
- - serializedVersion: 16
- name: Recon_Tank_Rig|Shoot
- takeName: Recon_Tank_Rig|Shoot
- firstFrame: 0
- lastFrame: 15
- wrapMode: 0
- orientationOffsetY: 0
- level: 0
- cycleOffset: 0
- loop: 0
- hasAdditiveReferencePose: 0
- loopTime: 0
- loopBlend: 0
- loopBlendOrientation: 0
- loopBlendPositionY: 0
- loopBlendPositionXZ: 0
- keepOriginalOrientation: 0
- keepOriginalPositionY: 1
- keepOriginalPositionXZ: 0
- heightFromFeet: 0
- mirror: 0
- bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
- curves: []
- events: []
- transformMask: []
- maskType: 3
- maskSource: {instanceID: 0}
- additiveReferencePoseFrame: 0
- isReadable: 1
- meshes:
- lODScreenPercentages: []
- globalScale: 0.15
- meshCompression: 0
- addColliders: 0
- useSRGBMaterialColor: 1
- importVisibility: 1
- importBlendShapes: 1
- importCameras: 1
- importLights: 1
- swapUVChannels: 0
- generateSecondaryUV: 0
- useFileUnits: 1
- optimizeMeshForGPU: 1
- keepQuads: 0
- weldVertices: 1
- preserveHierarchy: 0
- indexFormat: 0
- secondaryUVAngleDistortion: 8
- secondaryUVAreaDistortion: 15.000001
- secondaryUVHardAngle: 88
- secondaryUVPackMargin: 4
- useFileScale: 1
- previousCalculatedGlobalScale: 0.0015
- hasPreviousCalculatedGlobalScale: 1
- tangentSpace:
- normalSmoothAngle: 60
- normalImportMode: 0
- tangentImportMode: 3
- normalCalculationMode: 4
- legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
- blendShapeNormalImportMode: 1
- normalSmoothingSource: 0
- importAnimation: 1
- copyAvatar: 0
- humanDescription:
- serializedVersion: 2
- human: []
- skeleton: []
- armTwist: 0.5
- foreArmTwist: 0.5
- upperLegTwist: 0.5
- legTwist: 0.5
- armStretch: 0.05
- legStretch: 0.05
- feetSpacing: 0
- rootMotionBoneName:
- hasTranslationDoF: 0
- hasExtraRoot: 0
- skeletonHasParents: 1
- lastHumanDescriptionAvatarSource: {instanceID: 0}
- animationType: 2
- humanoidOversampling: 1
- additionalBone: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs.meta
deleted file mode 100644
index 6c92485..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 2baeb281f5e8e421582aa9f72e7f1702
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Projectile.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Projectile.prefab
deleted file mode 100644
index ec833f0..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Projectile.prefab
+++ /dev/null
@@ -1,247 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &63476987332307980
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 8035186136109819211}
- - component: {fileID: 9118274893554935717}
- - component: {fileID: 69063397099238371}
- m_Layer: 0
- m_Name: 3D Model
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &8035186136109819211
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 63476987332307980}
- m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 0.05, y: 0.1, z: 0.05}
- m_Children: []
- m_Father: {fileID: 24373266488650541}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
---- !u!33 &9118274893554935717
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 63476987332307980}
- m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
---- !u!23 &69063397099238371
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 63476987332307980}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: cba1b63a0bccc4b12ac25f05d0ae2dd1, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 0
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!1 &5890560936853567077
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 24373266488650541}
- - component: {fileID: 1713098107664522388}
- - component: {fileID: 2355290524794870353}
- - component: {fileID: 4629190479245867726}
- - component: {fileID: 7082621516996595528}
- m_Layer: 0
- m_Name: Projectile
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &24373266488650541
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5890560936853567077}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 8035186136109819211}
- - {fileID: 7830988697844474908}
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &1713098107664522388
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5890560936853567077}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 0
- m_AssetId: b7dd46dbf38c643f09e206f9fa4be008
- m_SceneId: 0
---- !u!136 &2355290524794870353
-CapsuleCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5890560936853567077}
- m_Material: {fileID: 0}
- m_IsTrigger: 1
- m_Enabled: 1
- m_Radius: 0.05
- m_Height: 0.2
- m_Direction: 1
- m_Center: {x: 0, y: 0, z: 0}
---- !u!54 &4629190479245867726
-Rigidbody:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5890560936853567077}
- serializedVersion: 2
- m_Mass: 1
- m_Drag: 0
- m_AngularDrag: 0.05
- m_UseGravity: 0
- m_IsKinematic: 0
- m_Interpolate: 1
- m_Constraints: 0
- m_CollisionDetection: 1
---- !u!114 &7082621516996595528
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 5890560936853567077}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 8f49b83f111a64bc7a5275af4f6f930b, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- destroyAfter: 5
- rigidBody: {fileID: 4629190479245867726}
- force: 1000
---- !u!1 &9126921595194253319
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 7830988697844474908}
- - component: {fileID: 4878977110396366525}
- m_Layer: 0
- m_Name: Point Light
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &7830988697844474908
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 9126921595194253319}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 24373266488650541}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!108 &4878977110396366525
-Light:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 9126921595194253319}
- m_Enabled: 1
- serializedVersion: 8
- m_Type: 2
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_Intensity: 5
- m_Range: 2
- m_SpotAngle: 30
- m_CookieSize: 10
- m_Shadows:
- m_Type: 0
- m_Resolution: -1
- m_CustomResolution: -1
- m_Strength: 1
- m_Bias: 0.05
- m_NormalBias: 0.4
- m_NearPlane: 0.2
- m_Cookie: {fileID: 0}
- m_DrawHalo: 0
- m_Flare: {fileID: 0}
- m_RenderMode: 0
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_Lightmapping: 4
- m_LightShadowCasterMode: 0
- m_AreaSize: {x: 1, y: 1}
- m_BounceIntensity: 3
- m_ColorTemperature: 6570
- m_UseColorTemperature: 0
- m_ShadowRadius: 0
- m_ShadowAngle: 0
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Projectile.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Projectile.prefab.meta
deleted file mode 100644
index f6d4068..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Projectile.prefab.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: b7dd46dbf38c643f09e206f9fa4be008
-PrefabImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Tank.prefab b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Tank.prefab
deleted file mode 100644
index ffed32e..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Tank.prefab
+++ /dev/null
@@ -1,314 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1 &1916082411674582
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 4492442352427800}
- - component: {fileID: 114118589361100106}
- - component: {fileID: 2240606817507776182}
- - component: {fileID: 114250499875391520}
- - component: {fileID: 6900008319038825817}
- - component: {fileID: 5194388907919410155}
- - component: {fileID: 114654712548978148}
- m_Layer: 0
- m_Name: Tank
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &4492442352427800
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1916082411674582}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children:
- - {fileID: 7831918942946891954}
- - {fileID: 6564220120147636086}
- - {fileID: 5718089106632469514}
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &114118589361100106
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1916082411674582}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- serverOnly: 0
- localPlayerAuthority: 1
- m_AssetId: 6f43bf5488a7443d19ab2a83c6b91f35
- m_SceneId: 0
---- !u!95 &2240606817507776182
-Animator:
- serializedVersion: 3
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1916082411674582}
- m_Enabled: 1
- m_Avatar: {fileID: 9000000, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- m_Controller: {fileID: 9100000, guid: a7211483bbd794b6d85ed88576e7d85c, type: 2}
- m_CullingMode: 0
- m_UpdateMode: 0
- m_ApplyRootMotion: 0
- m_LinearVelocityBlending: 0
- m_WarningMessage:
- m_HasTransformHierarchy: 1
- m_AllowConstantClipSamplingOptimization: 1
- m_KeepAnimatorControllerStateOnDisable: 0
---- !u!114 &114250499875391520
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1916082411674582}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- compressRotation: 1
---- !u!195 &6900008319038825817
-NavMeshAgent:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1916082411674582}
- m_Enabled: 1
- m_AgentTypeID: 0
- m_Radius: 0.5
- m_Speed: 1
- m_Acceleration: 1
- avoidancePriority: 50
- m_AngularSpeed: 120
- m_StoppingDistance: 0
- m_AutoTraverseOffMeshLink: 1
- m_AutoBraking: 1
- m_AutoRepath: 1
- m_Height: 0.5
- m_BaseOffset: 0
- m_WalkableMask: 4294967295
- m_ObstacleAvoidanceType: 0
---- !u!135 &5194388907919410155
-SphereCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1916082411674582}
- m_Material: {fileID: 0}
- m_IsTrigger: 1
- m_Enabled: 1
- serializedVersion: 2
- m_Radius: 0.5
- m_Center: {x: 0, y: 0.25, z: 0}
---- !u!114 &114654712548978148
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1916082411674582}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 7deadf756194d461e9140e42d651693b, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- syncMode: 0
- syncInterval: 0.1
- agent: {fileID: 6900008319038825817}
- animator: {fileID: 2240606817507776182}
- rotationSpeed: 80
- shootKey: 32
- projectilePrefab: {fileID: 5890560936853567077, guid: b7dd46dbf38c643f09e206f9fa4be008,
- type: 3}
- projectileMount: {fileID: 5718089106632469514}
---- !u!1 &4426914200102054949
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 6564220120147636086}
- - component: {fileID: 7604806193092689376}
- m_Layer: 0
- m_Name: Spot Light
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &6564220120147636086
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 4426914200102054949}
- m_LocalRotation: {x: 0.02281505, y: -0, z: -0, w: 0.9997397}
- m_LocalPosition: {x: 0.07, y: 0.46, z: 0.126}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 4492442352427800}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 2.615, y: 0, z: 0}
---- !u!108 &7604806193092689376
-Light:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 4426914200102054949}
- m_Enabled: 1
- serializedVersion: 8
- m_Type: 0
- m_Color: {r: 1, g: 0.9205329, b: 0.7877358, a: 1}
- m_Intensity: 3
- m_Range: 15
- m_SpotAngle: 80
- m_CookieSize: 10
- m_Shadows:
- m_Type: 2
- m_Resolution: -1
- m_CustomResolution: -1
- m_Strength: 1
- m_Bias: 0.05
- m_NormalBias: 0.4
- m_NearPlane: 0.2
- m_Cookie: {fileID: 0}
- m_DrawHalo: 0
- m_Flare: {fileID: 0}
- m_RenderMode: 0
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_Lightmapping: 4
- m_LightShadowCasterMode: 0
- m_AreaSize: {x: 1, y: 1}
- m_BounceIntensity: 1
- m_ColorTemperature: 6570
- m_UseColorTemperature: 0
- m_ShadowRadius: 0
- m_ShadowAngle: 0
---- !u!1 &4730779867780281009
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 5718089106632469514}
- m_Layer: 0
- m_Name: ProjectileMount
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &5718089106632469514
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 4730779867780281009}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0.412, z: 0.936}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 4492442352427800}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1001 &7831918942947279416
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- m_TransformParent: {fileID: 4492442352427800}
- m_Modifications:
- - target: {fileID: 100010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_Name
- value: 3D Model
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_LocalPosition.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_LocalPosition.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_LocalPosition.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_LocalRotation.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_LocalRotation.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_LocalRotation.w
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_RootOrder
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 13700000, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- propertyPath: m_Materials.Array.data[0]
- value:
- objectReference: {fileID: 2100000, guid: 2e67e42170aa64aa9a33424f8045ac89, type: 2}
- m_RemovedComponents:
- - {fileID: 9500000, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
- m_SourcePrefab: {fileID: 100100000, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
---- !u!4 &7831918942946891954 stripped
-Transform:
- m_CorrespondingSourceObject: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5,
- type: 3}
- m_PrefabInstance: {fileID: 7831918942947279416}
- m_PrefabAsset: {fileID: 0}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Tank.prefab.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Tank.prefab.meta
deleted file mode 100644
index 4454818..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Prefabs/Tank.prefab.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 6f43bf5488a7443d19ab2a83c6b91f35
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 100100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes.meta
deleted file mode 100644
index 5665d39..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 91225a3fc58fe4a7f9e10718cd3bdc61
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene.meta
deleted file mode 100644
index 01af532..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 81cfd31f234d94a0985fe946d2ce699f
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene.unity b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene.unity
deleted file mode 100644
index 8351a56..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene.unity
+++ /dev/null
@@ -1,655 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!29 &1
-OcclusionCullingSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_OcclusionBakeSettings:
- smallestOccluder: 5
- smallestHole: 0.25
- backfaceThreshold: 100
- m_SceneGUID: 00000000000000000000000000000000
- m_OcclusionCullingData: {fileID: 0}
---- !u!104 &2
-RenderSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 9
- m_Fog: 0
- m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
- m_FogMode: 3
- m_FogDensity: 0.01
- m_LinearFogStart: 0
- m_LinearFogEnd: 300
- m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
- m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
- m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
- m_AmbientIntensity: 1
- m_AmbientMode: 3
- m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
- m_SkyboxMaterial: {fileID: 0}
- m_HaloStrength: 0.5
- m_FlareStrength: 1
- m_FlareFadeSpeed: 3
- m_HaloTexture: {fileID: 0}
- m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
- m_DefaultReflectionMode: 0
- m_DefaultReflectionResolution: 128
- m_ReflectionBounces: 1
- m_ReflectionIntensity: 1
- m_CustomReflection: {fileID: 0}
- m_Sun: {fileID: 0}
- m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
- m_UseRadianceAmbientProbe: 0
---- !u!157 &3
-LightmapSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 11
- m_GIWorkflowMode: 1
- m_GISettings:
- serializedVersion: 2
- m_BounceScale: 1
- m_IndirectOutputScale: 1
- m_AlbedoBoost: 1
- m_EnvironmentLightingMode: 0
- m_EnableBakedLightmaps: 0
- m_EnableRealtimeLightmaps: 0
- m_LightmapEditorSettings:
- serializedVersion: 10
- m_Resolution: 2
- m_BakeResolution: 40
- m_AtlasSize: 1024
- m_AO: 0
- m_AOMaxDistance: 1
- m_CompAOExponent: 1
- m_CompAOExponentDirect: 0
- m_Padding: 2
- m_LightmapParameters: {fileID: 0}
- m_LightmapsBakeMode: 1
- m_TextureCompression: 1
- m_FinalGather: 0
- m_FinalGatherFiltering: 1
- m_FinalGatherRayCount: 256
- m_ReflectionCompression: 2
- m_MixedBakeMode: 2
- m_BakeBackend: 0
- m_PVRSampling: 1
- m_PVRDirectSampleCount: 32
- m_PVRSampleCount: 500
- m_PVRBounces: 2
- m_PVRFilterTypeDirect: 0
- m_PVRFilterTypeIndirect: 0
- m_PVRFilterTypeAO: 0
- m_PVRFilteringMode: 1
- m_PVRCulling: 1
- m_PVRFilteringGaussRadiusDirect: 1
- m_PVRFilteringGaussRadiusIndirect: 5
- m_PVRFilteringGaussRadiusAO: 2
- m_PVRFilteringAtrousPositionSigmaDirect: 0.5
- m_PVRFilteringAtrousPositionSigmaIndirect: 2
- m_PVRFilteringAtrousPositionSigmaAO: 1
- m_ShowResolutionOverlay: 1
- m_LightingDataAsset: {fileID: 0}
- m_UseShadowmask: 1
---- !u!196 &4
-NavMeshSettings:
- serializedVersion: 2
- m_ObjectHideFlags: 0
- m_BuildSettings:
- serializedVersion: 2
- agentTypeID: 0
- agentRadius: 0.5
- agentHeight: 2
- agentSlope: 45
- agentClimb: 0.4
- ledgeDropHeight: 0
- maxJumpAcrossDistance: 0
- minRegionArea: 2
- manualCellSize: 0
- cellSize: 0.16666667
- manualTileSize: 0
- tileSize: 256
- accuratePlacement: 0
- debug:
- m_Flags: 0
- m_NavMeshData: {fileID: 23800000, guid: 0bc607fa2e315482ebe98797e844e11f, type: 2}
---- !u!1 &88936773
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 88936777}
- - component: {fileID: 88936776}
- - component: {fileID: 88936775}
- - component: {fileID: 88936774}
- m_Layer: 0
- m_Name: Main Camera
- m_TagString: MainCamera
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!81 &88936774
-AudioListener:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 88936773}
- m_Enabled: 1
---- !u!124 &88936775
-Behaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 88936773}
- m_Enabled: 1
---- !u!20 &88936776
-Camera:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 88936773}
- m_Enabled: 1
- serializedVersion: 2
- m_ClearFlags: 1
- m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0}
- m_projectionMatrixMode: 1
- m_SensorSize: {x: 36, y: 24}
- m_LensShift: {x: 0, y: 0}
- m_GateFitMode: 2
- m_FocalLength: 50
- m_NormalizedViewPortRect:
- serializedVersion: 2
- x: 0
- y: 0
- width: 1
- height: 1
- near clip plane: 0.3
- far clip plane: 1000
- field of view: 60
- orthographic: 0
- orthographic size: 5
- m_Depth: -1
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_RenderingPath: -1
- m_TargetTexture: {fileID: 0}
- m_TargetDisplay: 0
- m_TargetEye: 3
- m_HDR: 1
- m_AllowMSAA: 1
- m_AllowDynamicResolution: 0
- m_ForceIntoRT: 0
- m_OcclusionCulling: 1
- m_StereoConvergence: 10
- m_StereoSeparation: 0.022
---- !u!4 &88936777
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 88936773}
- m_LocalRotation: {x: 0, y: 0.92387956, z: -0.38268343, w: 0}
- m_LocalPosition: {x: 0, y: 6.5, z: 8}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 0
- m_LocalEulerAnglesHint: {x: 45, y: 180, z: 0}
---- !u!1 &251893064
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 251893065}
- - component: {fileID: 251893066}
- m_Layer: 0
- m_Name: Spawn
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &251893065
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 251893064}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 3, y: 0, z: 3}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 6
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &251893066
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 251893064}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &535739935
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 535739936}
- - component: {fileID: 535739937}
- m_Layer: 0
- m_Name: Spawn
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &535739936
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 535739935}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 3, y: 0, z: -3}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 4
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &535739937
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 535739935}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &1107091652
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1107091656}
- - component: {fileID: 1107091655}
- - component: {fileID: 1107091654}
- - component: {fileID: 1107091653}
- m_Layer: 0
- m_Name: Ground
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 4294967295
- m_IsActive: 1
---- !u!23 &1107091653
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1107091652}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RenderingLayerMask: 4294967295
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 29b49c27a74f145918356859bd7af511, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_PreserveUVs: 1
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 0
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
---- !u!64 &1107091654
-MeshCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1107091652}
- m_Material: {fileID: 0}
- m_IsTrigger: 0
- m_Enabled: 1
- serializedVersion: 3
- m_Convex: 0
- m_CookingOptions: 14
- m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
---- !u!33 &1107091655
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1107091652}
- m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0}
---- !u!4 &1107091656
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1107091652}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 1
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1282001517
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1282001518}
- - component: {fileID: 1282001520}
- - component: {fileID: 1282001519}
- - component: {fileID: 1282001521}
- m_Layer: 0
- m_Name: NetworkManager
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1282001518
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1282001517}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 3
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &1282001519
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1282001517}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 6442dc8070ceb41f094e44de0bf87274, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- showGUI: 1
- offsetX: 0
- offsetY: 0
---- !u!114 &1282001520
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1282001517}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 8aab4c8111b7c411b9b92cf3dbc5bd4e, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- dontDestroyOnLoad: 1
- runInBackground: 1
- startOnHeadless: 1
- serverTickRate: 30
- showDebugMessages: 0
- offlineScene:
- onlineScene:
- transport: {fileID: 1282001521}
- networkAddress: localhost
- maxConnections: 4
- authenticator: {fileID: 0}
- playerPrefab: {fileID: 1916082411674582, guid: 6f43bf5488a7443d19ab2a83c6b91f35,
- type: 3}
- autoCreatePlayer: 1
- playerSpawnMethod: 1
- spawnPrefabs:
- - {fileID: 5890560936853567077, guid: b7dd46dbf38c643f09e206f9fa4be008, type: 3}
---- !u!114 &1282001521
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1282001517}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- OnClientConnected:
- m_PersistentCalls:
- m_Calls: []
- OnClientDataReceived:
- m_PersistentCalls:
- m_Calls: []
- OnClientError:
- m_PersistentCalls:
- m_Calls: []
- OnClientDisconnected:
- m_PersistentCalls:
- m_Calls: []
- OnServerConnected:
- m_PersistentCalls:
- m_Calls: []
- OnServerDataReceived:
- m_PersistentCalls:
- m_Calls: []
- OnServerError:
- m_PersistentCalls:
- m_Calls: []
- OnServerDisconnected:
- m_PersistentCalls:
- m_Calls: []
- port: 7777
- NoDelay: 1
- serverMaxMessageSize: 16384
- clientMaxMessageSize: 16384
---- !u!1 &1458789072
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1458789073}
- - component: {fileID: 1458789074}
- m_Layer: 0
- m_Name: Spawn
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1458789073
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1458789072}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: -3, y: 0, z: 3}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 7
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &1458789074
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1458789072}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &1501912662
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1501912663}
- - component: {fileID: 1501912664}
- m_Layer: 0
- m_Name: Spawn
- m_TagString: Untagged
- m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1501912663
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1501912662}
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: -3, y: 0, z: -3}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 5
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!114 &1501912664
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1501912662}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!1 &2054208274
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 2054208276}
- - component: {fileID: 2054208275}
- m_Layer: 0
- m_Name: Directional light
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!108 &2054208275
-Light:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2054208274}
- m_Enabled: 1
- serializedVersion: 8
- m_Type: 1
- m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_Intensity: 1
- m_Range: 10
- m_SpotAngle: 30
- m_CookieSize: 10
- m_Shadows:
- m_Type: 2
- m_Resolution: -1
- m_CustomResolution: -1
- m_Strength: 1
- m_Bias: 0.05
- m_NormalBias: 0.4
- m_NearPlane: 0.2
- m_Cookie: {fileID: 0}
- m_DrawHalo: 0
- m_Flare: {fileID: 0}
- m_RenderMode: 0
- m_CullingMask:
- serializedVersion: 2
- m_Bits: 4294967295
- m_Lightmapping: 4
- m_LightShadowCasterMode: 0
- m_AreaSize: {x: 1, y: 1}
- m_BounceIntensity: 1
- m_ColorTemperature: 6570
- m_UseColorTemperature: 0
- m_ShadowRadius: 0
- m_ShadowAngle: 0
---- !u!4 &2054208276
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 2054208274}
- m_LocalRotation: {x: 0.10938167, y: 0.8754261, z: -0.40821788, w: 0.23456976}
- m_LocalPosition: {x: 0, y: 10, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_Children: []
- m_Father: {fileID: 0}
- m_RootOrder: 2
- m_LocalEulerAnglesHint: {x: 50, y: 150, z: 0}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene.unity.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene.unity.meta
deleted file mode 100644
index c7f922e..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene.unity.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 83f9d2fb76f5742448c6e51f258327a2
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene/NavMesh.asset b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene/NavMesh.asset
deleted file mode 100644
index 3acffc8..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene/NavMesh.asset and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene/NavMesh.asset.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene/NavMesh.asset.meta
deleted file mode 100644
index 1997fe9..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scenes/Scene/NavMesh.asset.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 0bc607fa2e315482ebe98797e844e11f
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 23800000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts.meta
deleted file mode 100644
index e6be7b6..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 3815d4126f2934af187ce078c648bbc8
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Projectile.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Projectile.cs
deleted file mode 100644
index ee1db26..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Projectile.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using UnityEngine;
-
-namespace Mirror.Examples.Tanks
-{
- public class Projectile : NetworkBehaviour
- {
- public float destroyAfter = 5;
- public Rigidbody rigidBody;
- public float force = 1000;
-
- public override void OnStartServer()
- {
- Invoke(nameof(DestroySelf), destroyAfter);
- }
-
- // set velocity for server and client. this way we don't have to sync the
- // position, because both the server and the client simulate it.
- void Start()
- {
- rigidBody.AddForce(transform.forward * force);
- }
-
- // destroy for everyone on the server
- [Server]
- void DestroySelf()
- {
- NetworkServer.Destroy(gameObject);
- }
-
- // ServerCallback because we don't want a warning if OnTriggerEnter is
- // called on the client
- [ServerCallback]
- void OnTriggerEnter(Collider co)
- {
- NetworkServer.Destroy(gameObject);
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Projectile.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Projectile.cs.meta
deleted file mode 100644
index 387ece6..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Projectile.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 8f49b83f111a64bc7a5275af4f6f930b
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Tank.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Tank.cs
deleted file mode 100644
index 0a757dd..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Tank.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using UnityEngine;
-using UnityEngine.AI;
-
-namespace Mirror.Examples.Tanks
-{
- public class Tank : NetworkBehaviour
- {
- [Header("Components")]
- public NavMeshAgent agent;
- public Animator animator;
-
- [Header("Movement")]
- public float rotationSpeed = 100;
-
- [Header("Firing")]
- public KeyCode shootKey = KeyCode.Space;
- public GameObject projectilePrefab;
- public Transform projectileMount;
-
- void Update()
- {
- // movement for local player
- if (!isLocalPlayer) return;
-
- // rotate
- float horizontal = Input.GetAxis("Horizontal");
- transform.Rotate(0, horizontal * rotationSpeed * Time.deltaTime, 0);
-
- // move
- float vertical = Input.GetAxis("Vertical");
- Vector3 forward = transform.TransformDirection(Vector3.forward);
- agent.velocity = agent.speed * Mathf.Max(vertical, 0) * forward;
- animator.SetBool("Moving", agent.velocity != Vector3.zero);
-
- // shoot
- if (Input.GetKeyDown(shootKey))
- {
- CmdFire();
- }
- }
-
- // this is called on the server
- [Command]
- void CmdFire()
- {
- GameObject projectile = Instantiate(projectilePrefab, projectileMount.position, transform.rotation);
- NetworkServer.Spawn(projectile);
- RpcOnFire();
- }
-
- // this is called on the tank that fired for all observers
- [ClientRpc]
- void RpcOnFire()
- {
- animator.SetTrigger("Shoot");
- }
- }
-}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Tank.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Tank.cs.meta
deleted file mode 100644
index b7874c4..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Scripts/Tank.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 7deadf756194d461e9140e42d651693b
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures.meta
deleted file mode 100644
index fad816b..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 8ce6821cc1c644d5595ce9fc1f61debc
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture.meta
deleted file mode 100644
index a77c1ef..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 4e08c21c1034445fc834851f9e4202fe
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt Hand Painted Texture - License.txt b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt Hand Painted Texture - License.txt
deleted file mode 100644
index 6091137..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt Hand Painted Texture - License.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Dirt Hand Painted Textures created by 'KIIRA'
-https://opengameart.org/content/dirt-hand-painted-texture
-
-Licensed as CC-BY-3.0:
-https://creativecommons.org/licenses/by/3.0/
\ No newline at end of file
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt Hand Painted Texture - License.txt.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt Hand Painted Texture - License.txt.meta
deleted file mode 100644
index 4682e6c..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt Hand Painted Texture - License.txt.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 422e9f56a29ae488e836a23d1e0f21d0
-TextScriptImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt.mat
deleted file mode 100644
index 443aaff..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt.mat
+++ /dev/null
@@ -1,82 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Dirt
- m_Shader: {fileID: 45, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 5, y: 5}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 2800000, guid: bcc8fc05f1f924531a65f39394c0b703, type: 3}
- m_Scale: {x: 5, y: 5}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _SpecGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 1, g: 1, b: 1, a: 1}
- - _EmissionColor: {r: 0.13207549, g: 0.06631743, b: 0, a: 1}
- - _SpecColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt.mat.meta
deleted file mode 100644
index f571c8b..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/Dirt.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 29b49c27a74f145918356859bd7af511
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/dirt.png b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/dirt.png
deleted file mode 100644
index 3174ecc..0000000
Binary files a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/dirt.png and /dev/null differ
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/dirt.png.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/dirt.png.meta
deleted file mode 100644
index b00a626..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/(Public Domain) Dirt Hand Painted Texture/dirt.png.meta
+++ /dev/null
@@ -1,88 +0,0 @@
-fileFormatVersion: 2
-guid: bcc8fc05f1f924531a65f39394c0b703
-TextureImporter:
- fileIDToRecycleName: {}
- externalObjects: {}
- serializedVersion: 9
- mipmaps:
- mipMapMode: 0
- enableMipMap: 1
- sRGBTexture: 1
- linearTexture: 0
- fadeOut: 0
- borderMipMap: 0
- mipMapsPreserveCoverage: 0
- alphaTestReferenceValue: 0.5
- mipMapFadeDistanceStart: 1
- mipMapFadeDistanceEnd: 3
- bumpmap:
- convertToNormalMap: 0
- externalNormalMap: 0
- heightScale: 0.25
- normalMapFilter: 0
- isReadable: 0
- streamingMipmaps: 0
- streamingMipmapsPriority: 0
- grayScaleToAlpha: 0
- generateCubemap: 6
- cubemapConvolution: 0
- seamlessCubemap: 0
- textureFormat: 1
- maxTextureSize: 2048
- textureSettings:
- serializedVersion: 2
- filterMode: -1
- aniso: -1
- mipBias: -100
- wrapU: -1
- wrapV: -1
- wrapW: -1
- nPOTScale: 1
- lightmap: 0
- compressionQuality: 50
- spriteMode: 0
- spriteExtrude: 1
- spriteMeshType: 1
- alignment: 0
- spritePivot: {x: 0.5, y: 0.5}
- spritePixelsToUnits: 100
- spriteBorder: {x: 0, y: 0, z: 0, w: 0}
- spriteGenerateFallbackPhysicsShape: 1
- alphaUsage: 1
- alphaIsTransparency: 0
- spriteTessellationDetail: -1
- textureType: 0
- textureShape: 1
- singleChannelComponent: 0
- maxTextureSizeSet: 0
- compressionQualitySet: 0
- textureFormatSet: 0
- platformSettings:
- - serializedVersion: 2
- buildTarget: DefaultTexturePlatform
- maxTextureSize: 2048
- resizeAlgorithm: 0
- textureFormat: -1
- textureCompression: 1
- compressionQuality: 50
- crunchedCompression: 0
- allowsAlphaSplitting: 0
- overridden: 0
- androidETC2FallbackOverride: 0
- spriteSheet:
- serializedVersion: 2
- sprites: []
- outline: []
- physicsShape: []
- bones: []
- spriteID:
- vertices: []
- indices:
- edges: []
- weights: []
- spritePackingTag:
- pSDRemoveMatte: 0
- pSDShowRemoveMatteOption: 0
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/ProjectileMaterial.mat b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/ProjectileMaterial.mat
deleted file mode 100644
index d231b59..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/ProjectileMaterial.mat
+++ /dev/null
@@ -1,77 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!21 &2100000
-Material:
- serializedVersion: 6
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: ProjectileMaterial
- m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
- m_ShaderKeywords:
- m_LightmapFlags: 4
- m_EnableInstancingVariants: 0
- m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
- stringTagMap: {}
- disabledShaderPasses: []
- m_SavedProperties:
- serializedVersion: 3
- m_TexEnvs:
- - _BumpMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailAlbedoMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailMask:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _DetailNormalMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _EmissionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MainTex:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _MetallicGlossMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _OcclusionMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- - _ParallaxMap:
- m_Texture: {fileID: 0}
- m_Scale: {x: 1, y: 1}
- m_Offset: {x: 0, y: 0}
- m_Floats:
- - _BumpScale: 1
- - _Cutoff: 0.5
- - _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _GlossMapScale: 1
- - _Glossiness: 0
- - _GlossyReflections: 1
- - _Metallic: 0
- - _Mode: 0
- - _OcclusionStrength: 1
- - _Parallax: 0.02
- - _SmoothnessTextureChannel: 0
- - _SpecularHighlights: 1
- - _SrcBlend: 1
- - _UVSec: 0
- - _ZWrite: 1
- m_Colors:
- - _Color: {r: 0, g: 1, b: 0.8901961, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/ProjectileMaterial.mat.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/ProjectileMaterial.mat.meta
deleted file mode 100644
index 84c957e..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Examples/Tanks/Textures/ProjectileMaterial.mat.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: cba1b63a0bccc4b12ac25f05d0ae2dd1
-NativeFormatImporter:
- externalObjects: {}
- mainObjectFileID: 2100000
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/License.txt b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/License.txt
deleted file mode 100644
index 2925e86..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/License.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-The Mirror DLLs in the Plugins folder are MIT licensed:
-
-https://github.com/vis2k/Mirror
\ No newline at end of file
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/License.txt b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/License.txt
new file mode 100644
index 0000000..5f10030
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/License.txt
@@ -0,0 +1,23 @@
+Copyright (c) 2008 - 2015 Jb Evain
+Copyright (c) 2008 - 2011 Novell, Inc.
+
+https://github.com/jbevain/cecil
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/License.txt.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/License.txt.meta
similarity index 75%
rename from LiteNetLib4Mirror/Assets/MirrorLib/Mirror/License.txt.meta
rename to LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/License.txt.meta
index 6129dfe..9477cb6 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/License.txt.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/License.txt.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: dbf30d11d3879431f87403d009e47bf7
+guid: ab858db5ebbb0d542a9acd197669cb5a
TextScriptImporter:
externalObjects: {}
userData:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Mdb.dll.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Mdb.dll.meta
index f75f642..d5555bf 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Mdb.dll.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Mdb.dll.meta
@@ -10,17 +10,77 @@ PluginImporter:
isOverridable: 0
isExplicitlyReferenced: 0
platformData:
+ - first:
+ '': Any
+ second:
+ enabled: 0
+ settings:
+ Exclude Editor: 0
+ Exclude Linux: 1
+ Exclude Linux64: 1
+ Exclude LinuxUniversal: 1
+ Exclude OSXUniversal: 1
+ Exclude Win: 1
+ Exclude Win64: 1
- first:
Any:
second:
- enabled: 1
+ enabled: 0
settings: {}
- first:
Editor: Editor
second:
- enabled: 0
+ enabled: 1
settings:
DefaultValueInitialized: true
+ - first:
+ Facebook: Win
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Facebook: Win64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Linux
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Linux64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: LinuxUniversal
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: OSXUniversal
+ second:
+ enabled: 0
+ settings:
+ CPU: x86
+ - first:
+ Standalone: Win
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Win64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
- first:
Windows Store Apps: WindowsStoreApps
second:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Pdb.dll.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Pdb.dll.meta
index 773758f..3ab420f 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Pdb.dll.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Pdb.dll.meta
@@ -10,17 +10,77 @@ PluginImporter:
isOverridable: 0
isExplicitlyReferenced: 0
platformData:
+ - first:
+ '': Any
+ second:
+ enabled: 0
+ settings:
+ Exclude Editor: 0
+ Exclude Linux: 1
+ Exclude Linux64: 1
+ Exclude LinuxUniversal: 1
+ Exclude OSXUniversal: 1
+ Exclude Win: 1
+ Exclude Win64: 1
- first:
Any:
second:
- enabled: 1
+ enabled: 0
settings: {}
- first:
Editor: Editor
second:
- enabled: 0
+ enabled: 1
settings:
DefaultValueInitialized: true
+ - first:
+ Facebook: Win
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Facebook: Win64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Linux
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Linux64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: LinuxUniversal
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: OSXUniversal
+ second:
+ enabled: 0
+ settings:
+ CPU: x86
+ - first:
+ Standalone: Win
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Win64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
- first:
Windows Store Apps: WindowsStoreApps
second:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Rocks.dll.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Rocks.dll.meta
index a222084..aff0237 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Rocks.dll.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.Rocks.dll.meta
@@ -10,17 +10,77 @@ PluginImporter:
isOverridable: 0
isExplicitlyReferenced: 0
platformData:
+ - first:
+ '': Any
+ second:
+ enabled: 0
+ settings:
+ Exclude Editor: 0
+ Exclude Linux: 1
+ Exclude Linux64: 1
+ Exclude LinuxUniversal: 1
+ Exclude OSXUniversal: 1
+ Exclude Win: 1
+ Exclude Win64: 1
- first:
Any:
second:
- enabled: 1
+ enabled: 0
settings: {}
- first:
Editor: Editor
second:
- enabled: 0
+ enabled: 1
settings:
DefaultValueInitialized: true
+ - first:
+ Facebook: Win
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Facebook: Win64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Linux
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Linux64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: LinuxUniversal
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: OSXUniversal
+ second:
+ enabled: 0
+ settings:
+ CPU: x86
+ - first:
+ Standalone: Win
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Win64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
- first:
Windows Store Apps: WindowsStoreApps
second:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll.meta
index 73262f2..f87dc69 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Plugins/Mono.Cecil/Mono.CecilX.dll.meta
@@ -10,17 +10,79 @@ PluginImporter:
isOverridable: 0
isExplicitlyReferenced: 0
platformData:
+ - first:
+ '': Any
+ second:
+ enabled: 0
+ settings:
+ Exclude Editor: 0
+ Exclude Linux: 1
+ Exclude Linux64: 1
+ Exclude LinuxUniversal: 1
+ Exclude OSXUniversal: 1
+ Exclude Win: 1
+ Exclude Win64: 1
- first:
Any:
second:
- enabled: 1
+ enabled: 0
settings: {}
- first:
Editor: Editor
second:
- enabled: 0
+ enabled: 1
settings:
+ CPU: AnyCPU
DefaultValueInitialized: true
+ OS: AnyOS
+ - first:
+ Facebook: Win
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Facebook: Win64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Linux
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Linux64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: LinuxUniversal
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: OSXUniversal
+ second:
+ enabled: 0
+ settings:
+ CPU: x86
+ - first:
+ Standalone: Win
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Win64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
- first:
Windows Store Apps: WindowsStoreApps
second:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Readme.txt b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Readme.txt
index a62cf78..fb011f3 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Readme.txt
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Readme.txt
@@ -4,7 +4,7 @@ and several MMO projects in development.
*** IMPORTANT -- You must restart Unity after importing Mirror for the Components Menu to update! ***
Requirements:
- Unity 2018.3.6+
+ Unity 2018.4 LTS
Runtime .Net 4.x (Project Settings > Player > Other Settings)
Documentation:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/AssemblyInfo.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/AssemblyInfo.cs
index f0c4858..ea866b0 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/AssemblyInfo.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/AssemblyInfo.cs
@@ -1,3 +1,8 @@
-using System.Runtime.CompilerServices;
+using System.Runtime.CompilerServices;
-[assembly: InternalsVisibleTo("Mirror.Tests")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("Mirror.Tests.Common")]
+[assembly: InternalsVisibleTo("Mirror.Tests")]
+[assembly: InternalsVisibleTo("Mirror.Tests.Runtime")]
+[assembly: InternalsVisibleTo("Mirror.Tests.Performance.Editor")]
+[assembly: InternalsVisibleTo("Mirror.Tests.Performance.Runtime")]
+[assembly: InternalsVisibleTo("Mirror.Editor")]
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/ClientScene.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/ClientScene.cs
index eb7adf0..1b41b73 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/ClientScene.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/ClientScene.cs
@@ -18,12 +18,31 @@ namespace Mirror
///
public static class ClientScene
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(ClientScene));
+
static bool isSpawnFinished;
+ static NetworkIdentity _localPlayer;
///
/// NetworkIdentity of the localPlayer
///
- public static NetworkIdentity localPlayer { get; private set; }
+ public static NetworkIdentity localPlayer
+ {
+ get => _localPlayer;
+ private set
+ {
+ NetworkIdentity oldPlayer = _localPlayer;
+ NetworkIdentity newPlayer = value;
+ if (oldPlayer != newPlayer)
+ {
+ _localPlayer = value;
+ onLocalPlayerChanged?.Invoke(oldPlayer, newPlayer);
+ }
+ }
+ }
+
+ public delegate void LocalplayerChanged(NetworkIdentity oldPlayer, NetworkIdentity newPlayer);
+ public static event LocalplayerChanged onLocalPlayerChanged;
///
/// Returns true when a client's connection has been set to ready.
@@ -31,11 +50,11 @@ public static class ClientScene
/// This is read-only. To change the ready state of a client, use ClientScene.Ready(). The server is able to set the ready state of clients using NetworkServer.SetClientReady(), NetworkServer.SetClientNotReady() and NetworkServer.SetAllClientsNotReady().
/// This is done when changing scenes so that clients don't receive state update messages during scene loading.
///
- public static bool ready { get; internal set; }
+ public static bool ready { get; set; }
///
/// The NetworkConnection object that is currently "ready". This is the connection to the server where objects are spawned from.
- /// This connection can be used to send messages to the server. There can only be one ready connection at a time. There can be multiple NetworkClient instances in existence, each with their own NetworkConnections, but there is only one ClientScene instance and corresponding ready connection.
+ /// This connection can be used to send messages to the server. There can only be one ClientScene and ready connection at a time.
///
public static NetworkConnection readyConnection { get; private set; }
@@ -43,24 +62,22 @@ public static class ClientScene
/// This is a dictionary of the prefabs that are registered on the client with ClientScene.RegisterPrefab().
/// The key to the dictionary is the prefab asset Id.
///
- public static Dictionary prefabs = new Dictionary();
+ public static readonly Dictionary prefabs = new Dictionary();
///
/// This is dictionary of the disabled NetworkIdentity objects in the scene that could be spawned by messages from the server.
/// The key to the dictionary is the NetworkIdentity sceneId.
///
- public static Dictionary spawnableObjects;
+ public static readonly Dictionary spawnableObjects = new Dictionary();
// spawn handlers
- static readonly Dictionary spawnHandlers = new Dictionary();
- static readonly Dictionary unspawnHandlers = new Dictionary();
+ internal static readonly Dictionary spawnHandlers = new Dictionary();
+ internal static readonly Dictionary unspawnHandlers = new Dictionary();
- // this is never called, and if we do call it in NetworkClient.Shutdown
- // then the client's player object won't be removed after disconnecting!
internal static void Shutdown()
{
ClearSpawners();
- spawnableObjects = null;
+ spawnableObjects.Clear();
readyConnection = null;
ready = false;
isSpawnFinished = false;
@@ -70,43 +87,33 @@ internal static void Shutdown()
// this is called from message handler for Owner message
internal static void InternalAddPlayer(NetworkIdentity identity)
{
- if (LogFilter.Debug) Debug.LogWarning("ClientScene.InternalAddPlayer");
+ logger.Log("ClientScene.InternalAddPlayer");
// NOTE: It can be "normal" when changing scenes for the player to be destroyed and recreated.
// But, the player structures are not cleaned up, we'll just replace the old player
localPlayer = identity;
+
+ // NOTE: we DONT need to set isClient=true here, because OnStartClient
+ // is called before OnStartLocalPlayer, hence it's already set.
+ // localPlayer.isClient = true;
+
if (readyConnection != null)
{
readyConnection.identity = identity;
}
else
{
- Debug.LogWarning("No ready connection found for setting player controller during InternalAddPlayer");
+ logger.LogWarning("No ready connection found for setting player controller during InternalAddPlayer");
}
}
- ///
- /// This adds a player GameObject for this client.
- /// This causes an AddPlayer message to be sent to the server, and NetworkManager.OnServerAddPlayer is called.
- ///
- /// True if player was added.
- public static bool AddPlayer() => AddPlayer(null);
-
- ///
- /// This adds a player GameObject for this client. This causes an AddPlayer message to be sent to the server, and NetworkManager.OnServerAddPlayer is called. If an extra message was passed to AddPlayer, then OnServerAddPlayer will be called with a NetworkReader that contains the contents of the message.
- ///
- /// The connection to become ready for this client.
- /// True if player was added.
- public static bool AddPlayer(NetworkConnection readyConn) => AddPlayer(readyConn, null);
-
///
/// This adds a player GameObject for this client. This causes an AddPlayer message to be sent to the server, and NetworkManager.OnServerAddPlayer is called. If an extra message was passed to AddPlayer, then OnServerAddPlayer will be called with a NetworkReader that contains the contents of the message.
/// extraMessage can contain character selection, etc.
///
/// The connection to become ready for this client.
- /// An extra message object that can be passed to the server for this player.
/// True if player was added.
- public static bool AddPlayer(NetworkConnection readyConn, byte[] extraData)
+ public static bool AddPlayer(NetworkConnection readyConn)
{
// ensure valid ready connection
if (readyConn != null)
@@ -117,49 +124,28 @@ public static bool AddPlayer(NetworkConnection readyConn, byte[] extraData)
if (!ready)
{
- Debug.LogError("Must call AddPlayer() with a connection the first time to become ready.");
+ logger.LogError("Must call AddPlayer() with a connection the first time to become ready.");
return false;
}
if (readyConnection.identity != null)
{
- Debug.LogError("ClientScene.AddPlayer: a PlayerController was already added. Did you call AddPlayer twice?");
+ logger.LogError("ClientScene.AddPlayer: a PlayerController was already added. Did you call AddPlayer twice?");
return false;
}
- if (LogFilter.Debug) Debug.Log("ClientScene.AddPlayer() called with connection [" + readyConnection + "]");
+ if (logger.LogEnabled()) logger.Log("ClientScene.AddPlayer() called with connection [" + readyConnection + "]");
- AddPlayerMessage message = new AddPlayerMessage()
- {
-#pragma warning disable CS0618 // Type or member is obsolete
- value = extraData
-#pragma warning restore CS0618 // Type or member is obsolete
- };
- readyConnection.Send(message);
+ readyConnection.Send(new AddPlayerMessage());
return true;
}
+ // Deprecated 5/2/2020
///
- /// Removes the player from the game.
+ /// Obsolete: Removed as a security risk. Use NetworkServer.RemovePlayerForConnection instead.
///
- /// True if succcessful
- public static bool RemovePlayer()
- {
- if (LogFilter.Debug) Debug.Log("ClientScene.RemovePlayer() called with connection [" + readyConnection + "]");
-
- if (readyConnection.identity != null)
- {
- readyConnection.Send(new RemovePlayerMessage());
-
- Object.Destroy(readyConnection.identity.gameObject);
-
- readyConnection.identity = null;
- localPlayer = null;
-
- return true;
- }
- return false;
- }
+ [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Removed as a security risk. Use NetworkServer.RemovePlayerForConnection(NetworkConnection conn, bool keepAuthority = false) instead", true)]
+ public static bool RemovePlayer() { return false; }
///
/// Signal that the client connection is ready to enter the game.
@@ -171,21 +157,26 @@ public static bool Ready(NetworkConnection conn)
{
if (ready)
{
- Debug.LogError("A connection has already been set as ready. There can only be one.");
+ logger.LogError("A connection has already been set as ready. There can only be one.");
return false;
}
- if (LogFilter.Debug) Debug.Log("ClientScene.Ready() called with connection [" + conn + "]");
+ if (logger.LogEnabled()) logger.Log("ClientScene.Ready() called with connection [" + conn + "]");
if (conn != null)
{
- conn.Send(new ReadyMessage());
+ // Set these before sending the ReadyMessage, otherwise host client
+ // will fail in InternalAddPlayer with null readyConnection.
ready = true;
readyConnection = conn;
readyConnection.isReady = true;
+
+ // Tell server we're ready to have a player object spawned
+ conn.Send(new ReadyMessage());
+
return true;
}
- Debug.LogError("Ready() called with invalid connection object: conn=null");
+ logger.LogError("Ready() called with invalid connection object: conn=null");
return false;
}
@@ -198,6 +189,9 @@ internal static void HandleClientDisconnect(NetworkConnection conn)
}
}
+ ///
+ /// Checks if identity is not spawned yet, not hidden and has sceneId
+ ///
static bool ConsiderForSpawning(NetworkIdentity identity)
{
// not spawned yet, not hidden, etc.?
@@ -212,21 +206,19 @@ static bool ConsiderForSpawning(NetworkIdentity identity)
///
public static void PrepareToSpawnSceneObjects()
{
- // add all unspawned NetworkIdentities to spawnable objects
- spawnableObjects = Resources.FindObjectsOfTypeAll()
- .Where(ConsiderForSpawning)
- .ToDictionary(identity => identity.sceneId, identity => identity);
- }
+ // remove existing items, they will be re-added below
+ spawnableObjects.Clear();
- static NetworkIdentity SpawnSceneObject(ulong sceneId)
- {
- if (spawnableObjects.TryGetValue(sceneId, out NetworkIdentity identity))
+ // finds all NetworkIdentity currently loaded by unity (includes disabled objects)
+ NetworkIdentity[] allIdentities = Resources.FindObjectsOfTypeAll();
+ foreach (NetworkIdentity identity in allIdentities)
{
- spawnableObjects.Remove(sceneId);
- return identity;
+ // add all unspawned NetworkIdentities to spawnable objects
+ if (ConsiderForSpawning(identity))
+ {
+ spawnableObjects.Add(identity.sceneId, identity);
+ }
}
- Debug.LogWarning("Could not find scene object with sceneid:" + sceneId.ToString("X"));
- return null;
}
///
@@ -243,28 +235,85 @@ public static bool GetPrefab(Guid assetId, out GameObject prefab)
prefabs.TryGetValue(assetId, out prefab) && prefab != null;
}
+ ///
+ /// Valids Prefab then adds it to prefabs dictionary
+ ///
+ /// NetworkIdentity on Prefab GameObject
+ static void RegisterPrefabIdentity(NetworkIdentity prefab)
+ {
+ if (prefab.assetId == Guid.Empty)
+ {
+ logger.LogError($"Can not Register '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead");
+ return;
+ }
+
+ if (prefab.sceneId != 0)
+ {
+ logger.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
+ return;
+ }
+
+ NetworkIdentity[] identities = prefab.GetComponentsInChildren();
+ if (identities.Length > 1)
+ {
+ logger.LogWarning($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object.");
+ }
+
+ if (prefabs.ContainsKey(prefab.assetId))
+ {
+ GameObject existingPrefab = prefabs[prefab.assetId];
+ logger.LogWarning($"Replacing existing prefab with assetId '{prefab.assetId}'. Old prefab '{existingPrefab.name}', New prefab '{prefab.name}'");
+ }
+
+ if (spawnHandlers.ContainsKey(prefab.assetId) || unspawnHandlers.ContainsKey(prefab.assetId))
+ {
+ logger.LogWarning($"Adding prefab '{prefab.name}' with assetId '{prefab.assetId}' when spawnHandlers with same assetId already exists.");
+ }
+
+ if (logger.LogEnabled()) logger.Log($"Registering prefab '{prefab.name}' as asset:{prefab.assetId}");
+
+ prefabs[prefab.assetId] = prefab.gameObject;
+ }
+
///
/// Registers a prefab with the spawning system.
/// When a NetworkIdentity object is spawned on a server with NetworkServer.SpawnObject(), and the prefab that the object was created from was registered with RegisterPrefab(), the client will use that prefab to instantiate a corresponding client object with the same netId.
/// The NetworkManager has a list of spawnable prefabs, it uses this function to register those prefabs with the ClientScene.
/// The set of current spawnable object is available in the ClientScene static member variable ClientScene.prefabs, which is a dictionary of NetworkAssetIds and prefab references.
+ /// NOTE: newAssetId can not be set on GameObjects that already have an assetId
///
- /// A Prefab that will be spawned.
- /// An assetId to be assigned to this prefab. This allows a dynamically created game object to be registered for an already known asset Id.
+ /// A GameObject that will be spawned.
+ /// An assetId to be assigned to this GameObject. This allows a dynamically created game object to be registered for an already known asset Id.
public static void RegisterPrefab(GameObject prefab, Guid newAssetId)
{
- NetworkIdentity identity = prefab.GetComponent();
- if (identity)
+ if (prefab == null)
+ {
+ logger.LogError("Could not register prefab because it was null");
+ return;
+ }
+
+ if (newAssetId == Guid.Empty)
{
- identity.assetId = newAssetId;
+ logger.LogError($"Could not register '{prefab.name}' with new assetId because the new assetId was empty");
+ return;
+ }
- if (LogFilter.Debug) Debug.Log("Registering prefab '" + prefab.name + "' as asset:" + identity.assetId);
- prefabs[identity.assetId] = prefab;
+ NetworkIdentity identity = prefab.GetComponent();
+ if (identity == null)
+ {
+ logger.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component");
+ return;
}
- else
+
+ if (identity.assetId != Guid.Empty && identity.assetId != newAssetId)
{
- Debug.LogError("Could not register '" + prefab.name + "' since it contains no NetworkIdentity component");
+ logger.LogError($"Could not register '{prefab.name}' to {newAssetId} because it already had an AssetId, Existing assetId {identity.assetId}");
+ return;
}
+
+ identity.assetId = newAssetId;
+
+ RegisterPrefabIdentity(identity);
}
///
@@ -276,23 +325,43 @@ public static void RegisterPrefab(GameObject prefab, Guid newAssetId)
/// A Prefab that will be spawned.
public static void RegisterPrefab(GameObject prefab)
{
- NetworkIdentity identity = prefab.GetComponent();
- if (identity)
+ if (prefab == null)
{
- if (LogFilter.Debug) Debug.Log("Registering prefab '" + prefab.name + "' as asset:" + identity.assetId);
- prefabs[identity.assetId] = prefab;
+ logger.LogError("Could not register prefab because it was null");
+ return;
+ }
- NetworkIdentity[] identities = prefab.GetComponentsInChildren();
- if (identities.Length > 1)
- {
- Debug.LogWarning("The prefab '" + prefab.name +
- "' has multiple NetworkIdentity components. There can only be one NetworkIdentity on a prefab, and it must be on the root object.");
- }
+ NetworkIdentity identity = prefab.GetComponent();
+ if (identity == null)
+ {
+ logger.LogError($"Could not register '{prefab.name}' since it contains no NetworkIdentity component");
+ return;
}
- else
+
+ RegisterPrefabIdentity(identity);
+ }
+
+ ///
+ /// Registers a prefab with the spawning system.
+ /// When a NetworkIdentity object is spawned on a server with NetworkServer.SpawnObject(), and the prefab that the object was created from was registered with RegisterPrefab(), the client will use that prefab to instantiate a corresponding client object with the same netId.
+ /// The NetworkManager has a list of spawnable prefabs, it uses this function to register those prefabs with the ClientScene.
+ /// The set of current spawnable object is available in the ClientScene static member variable ClientScene.prefabs, which is a dictionary of NetworkAssetIds and prefab references.
+ /// NOTE: newAssetId can not be set on GameObjects that already have an assetId
+ ///
+ /// A GameObject that will be spawned.
+ /// An assetId to be assigned to this GameObject. This allows a dynamically created game object to be registered for an already known asset Id.
+ /// A method to use as a custom spawnhandler on clients.
+ /// A method to use as a custom un-spawnhandler on clients.
+ public static void RegisterPrefab(GameObject prefab, Guid newAssetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
+ {
+ // We need this check here because we don't want a null handler in the lambda expression below
+ if (spawnHandler == null)
{
- Debug.LogError("Could not register '" + prefab.name + "' since it contains no NetworkIdentity component");
+ logger.LogError($"Can not Register null SpawnHandler for {newAssetId}");
+ return;
}
+
+ RegisterPrefab(prefab, newAssetId, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler);
}
///
@@ -306,29 +375,196 @@ public static void RegisterPrefab(GameObject prefab)
/// A method to use as a custom un-spawnhandler on clients.
public static void RegisterPrefab(GameObject prefab, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
{
+ if (prefab == null)
+ {
+ logger.LogError("Could not register handler for prefab because the prefab was null");
+ return;
+ }
+
NetworkIdentity identity = prefab.GetComponent();
if (identity == null)
{
- Debug.LogError("Could not register '" + prefab.name + "' since it contains no NetworkIdentity component");
+ logger.LogError("Could not register handler for '" + prefab.name + "' since it contains no NetworkIdentity component");
return;
}
- if (spawnHandler == null || unspawnHandler == null)
+ if (identity.sceneId != 0)
{
- Debug.LogError("RegisterPrefab custom spawn function null for " + identity.assetId);
+ logger.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
return;
}
- if (identity.assetId == Guid.Empty)
+ Guid assetId = identity.assetId;
+
+ if (assetId == Guid.Empty)
{
- Debug.LogError("RegisterPrefab game object " + prefab.name + " has no prefab. Use RegisterSpawnHandler() instead?");
+ logger.LogError($"Can not Register handler for '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead");
return;
}
- if (LogFilter.Debug) Debug.Log("Registering custom prefab '" + prefab.name + "' as asset:" + identity.assetId + " " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
+ // We need this check here because we don't want a null handler in the lambda expression below
+ if (spawnHandler == null)
+ {
+ logger.LogError($"Can not Register null SpawnHandler for {assetId}");
+ return;
+ }
- spawnHandlers[identity.assetId] = spawnHandler;
- unspawnHandlers[identity.assetId] = unspawnHandler;
+ RegisterPrefab(prefab, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler);
+ }
+
+ ///
+ /// Registers a prefab with the spawning system.
+ /// When a NetworkIdentity object is spawned on a server with NetworkServer.SpawnObject(), and the prefab that the object was created from was registered with RegisterPrefab(), the client will use that prefab to instantiate a corresponding client object with the same netId.
+ /// The NetworkManager has a list of spawnable prefabs, it uses this function to register those prefabs with the ClientScene.
+ /// The set of current spawnable object is available in the ClientScene static member variable ClientScene.prefabs, which is a dictionary of NetworkAssetIds and prefab references.
+ /// NOTE: newAssetId can not be set on GameObjects that already have an assetId
+ ///
+ /// A GameObject that will be spawned.
+ /// An assetId to be assigned to this GameObject. This allows a dynamically created game object to be registered for an already known asset Id.
+ /// A method to use as a custom spawnhandler on clients.
+ /// A method to use as a custom un-spawnhandler on clients.
+ public static void RegisterPrefab(GameObject prefab, Guid newAssetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
+ {
+ if (newAssetId == Guid.Empty)
+ {
+ logger.LogError($"Could not register handler for '{prefab.name}' with new assetId because the new assetId was empty");
+ return;
+ }
+
+ if (prefab == null)
+ {
+ logger.LogError("Could not register handler for prefab because the prefab was null");
+ return;
+ }
+
+ NetworkIdentity identity = prefab.GetComponent();
+ if (identity == null)
+ {
+ logger.LogError("Could not register handler for '" + prefab.name + "' since it contains no NetworkIdentity component");
+ return;
+ }
+
+ if (identity.assetId != Guid.Empty && identity.assetId != newAssetId)
+ {
+ logger.LogError($"Could not register Handler for '{prefab.name}' to {newAssetId} because it already had an AssetId, Existing assetId {identity.assetId}");
+ return;
+ }
+
+ if (identity.sceneId != 0)
+ {
+ logger.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
+ return;
+ }
+
+ identity.assetId = newAssetId;
+ Guid assetId = identity.assetId;
+
+ if (spawnHandler == null)
+ {
+ logger.LogError($"Can not Register null SpawnHandler for {assetId}");
+ return;
+ }
+
+ if (unspawnHandler == null)
+ {
+ logger.LogError($"Can not Register null UnSpawnHandler for {assetId}");
+ return;
+ }
+
+ if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId))
+ {
+ logger.LogWarning($"Replacing existing spawnHandlers for prefab '{prefab.name}' with assetId '{assetId}'");
+ }
+
+ if (prefabs.ContainsKey(assetId))
+ {
+ // this is error because SpawnPrefab checks prefabs before handler
+ logger.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}', unregister the prefab first before trying to add handler");
+ }
+
+ NetworkIdentity[] identities = prefab.GetComponentsInChildren();
+ if (identities.Length > 1)
+ {
+ logger.LogWarning($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object.");
+ }
+
+ if (logger.LogEnabled()) logger.Log("Registering custom prefab '" + prefab.name + "' as asset:" + assetId + " " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
+
+ spawnHandlers[assetId] = spawnHandler;
+ unspawnHandlers[assetId] = unspawnHandler;
+ }
+
+ ///
+ /// Registers a prefab with the spawning system.
+ /// When a NetworkIdentity object is spawned on a server with NetworkServer.SpawnObject(), and the prefab that the object was created from was registered with RegisterPrefab(), the client will use that prefab to instantiate a corresponding client object with the same netId.
+ /// The NetworkManager has a list of spawnable prefabs, it uses this function to register those prefabs with the ClientScene.
+ /// The set of current spawnable object is available in the ClientScene static member variable ClientScene.prefabs, which is a dictionary of NetworkAssetIds and prefab references.
+ ///
+ /// A Prefab that will be spawned.
+ /// A method to use as a custom spawnhandler on clients.
+ /// A method to use as a custom un-spawnhandler on clients.
+ public static void RegisterPrefab(GameObject prefab, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
+ {
+ if (prefab == null)
+ {
+ logger.LogError("Could not register handler for prefab because the prefab was null");
+ return;
+ }
+
+ NetworkIdentity identity = prefab.GetComponent();
+ if (identity == null)
+ {
+ logger.LogError("Could not register handler for '" + prefab.name + "' since it contains no NetworkIdentity component");
+ return;
+ }
+
+ if (identity.sceneId != 0)
+ {
+ logger.LogError($"Can not Register '{prefab.name}' because it has a sceneId, make sure you are passing in the original prefab and not an instance in the scene.");
+ return;
+ }
+
+ Guid assetId = identity.assetId;
+
+ if (assetId == Guid.Empty)
+ {
+ logger.LogError($"Can not Register handler for '{prefab.name}' because it had empty assetid. If this is a scene Object use RegisterSpawnHandler instead");
+ return;
+ }
+
+ if (spawnHandler == null)
+ {
+ logger.LogError($"Can not Register null SpawnHandler for {assetId}");
+ return;
+ }
+
+ if (unspawnHandler == null)
+ {
+ logger.LogError($"Can not Register null UnSpawnHandler for {assetId}");
+ return;
+ }
+
+ if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId))
+ {
+ logger.LogWarning($"Replacing existing spawnHandlers for prefab '{prefab.name}' with assetId '{assetId}'");
+ }
+
+ if (prefabs.ContainsKey(assetId))
+ {
+ // this is error because SpawnPrefab checks prefabs before handler
+ logger.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}', unregister the prefab first before trying to add handler");
+ }
+
+ NetworkIdentity[] identities = prefab.GetComponentsInChildren();
+ if (identities.Length > 1)
+ {
+ logger.LogWarning($"Prefab '{prefab.name}' has multiple NetworkIdentity components. There should only be one NetworkIdentity on a prefab, and it must be on the root object.");
+ }
+
+ if (logger.LogEnabled()) logger.Log("Registering custom prefab '" + prefab.name + "' as asset:" + assetId + " " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
+
+ spawnHandlers[assetId] = spawnHandler;
+ unspawnHandlers[assetId] = unspawnHandler;
}
///
@@ -337,14 +573,24 @@ public static void RegisterPrefab(GameObject prefab, SpawnDelegate spawnHandler,
/// The prefab to be removed from registration.
public static void UnregisterPrefab(GameObject prefab)
{
+ if (prefab == null)
+ {
+ logger.LogError("Could not unregister prefab because it was null");
+ return;
+ }
+
NetworkIdentity identity = prefab.GetComponent();
if (identity == null)
{
- Debug.LogError("Could not unregister '" + prefab.name + "' since it contains no NetworkIdentity component");
+ logger.LogError("Could not unregister '" + prefab.name + "' since it contains no NetworkIdentity component");
return;
}
- spawnHandlers.Remove(identity.assetId);
- unspawnHandlers.Remove(identity.assetId);
+
+ Guid assetId = identity.assetId;
+
+ prefabs.Remove(assetId);
+ spawnHandlers.Remove(assetId);
+ unspawnHandlers.Remove(assetId);
}
///
@@ -356,13 +602,55 @@ public static void UnregisterPrefab(GameObject prefab)
/// A method to use as a custom un-spawnhandler on clients.
public static void RegisterSpawnHandler(Guid assetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
{
- if (spawnHandler == null || unspawnHandler == null)
+ // We need this check here because we don't want a null handler in the lambda expression below
+ if (spawnHandler == null)
{
- Debug.LogError("RegisterSpawnHandler custom spawn function null for " + assetId);
+ logger.LogError($"Can not Register null SpawnHandler for {assetId}");
return;
}
- if (LogFilter.Debug) Debug.Log("RegisterSpawnHandler asset '" + assetId + "' " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
+ RegisterSpawnHandler(assetId, msg => spawnHandler(msg.position, msg.assetId), unspawnHandler);
+ }
+
+ ///
+ /// This is an advanced spawning function that registers a custom assetId with the UNET spawning system.
+ /// This can be used to register custom spawning methods for an assetId - instead of the usual method of registering spawning methods for a prefab. This should be used when no prefab exists for the spawned objects - such as when they are constructed dynamically at runtime from configuration data.
+ ///
+ /// Custom assetId string.
+ /// A method to use as a custom spawnhandler on clients.
+ /// A method to use as a custom un-spawnhandler on clients.
+ public static void RegisterSpawnHandler(Guid assetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
+ {
+ if (spawnHandler == null)
+ {
+ logger.LogError($"Can not Register null SpawnHandler for {assetId}");
+ return;
+ }
+
+ if (unspawnHandler == null)
+ {
+ logger.LogError($"Can not Register null UnSpawnHandler for {assetId}");
+ return;
+ }
+
+ if (assetId == Guid.Empty)
+ {
+ logger.LogError("Can not Register SpawnHandler for empty Guid");
+ return;
+ }
+
+ if (spawnHandlers.ContainsKey(assetId) || unspawnHandlers.ContainsKey(assetId))
+ {
+ logger.LogWarning($"Replacing existing spawnHandlers for {assetId}");
+ }
+
+ if (prefabs.ContainsKey(assetId))
+ {
+ // this is error because SpawnPrefab checks prefabs before handler
+ logger.LogError($"assetId '{assetId}' is already used by prefab '{prefabs[assetId].name}'");
+ }
+
+ if (logger.LogEnabled()) logger.Log("RegisterSpawnHandler asset '" + assetId + "' " + spawnHandler.GetMethodName() + "/" + unspawnHandler.GetMethodName());
spawnHandlers[assetId] = spawnHandler;
unspawnHandlers[assetId] = unspawnHandler;
@@ -404,221 +692,209 @@ static bool InvokeUnSpawnHandler(Guid assetId, GameObject obj)
///
public static void DestroyAllClientObjects()
{
- foreach (NetworkIdentity identity in NetworkIdentity.spawned.Values)
+ // user can modify spawned lists which causes InvalidOperationException
+ // list can modified either in UnSpawnHandler or in OnDisable/OnDestroy
+ // we need the Try/Catch so that the rest of the shutdown does not get stopped
+ try
{
- if (identity != null && identity.gameObject != null)
+ foreach (NetworkIdentity identity in NetworkIdentity.spawned.Values)
{
- if (!InvokeUnSpawnHandler(identity.assetId, identity.gameObject))
+ if (identity != null && identity.gameObject != null)
{
- if (identity.sceneId == 0)
- {
- Object.Destroy(identity.gameObject);
- }
- else
+ bool wasUnspawned = InvokeUnSpawnHandler(identity.assetId, identity.gameObject);
+ if (!wasUnspawned)
{
- identity.MarkForReset();
- identity.gameObject.SetActive(false);
+ if (identity.sceneId == 0)
+ {
+ Object.Destroy(identity.gameObject);
+ }
+ else
+ {
+ identity.Reset();
+ identity.gameObject.SetActive(false);
+ }
}
}
}
+ NetworkIdentity.spawned.Clear();
}
- NetworkIdentity.spawned.Clear();
- }
-
- ///
- /// Obsolete: Use instead.
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use NetworkIdentity.spawned[netId] instead.")]
- public static GameObject FindLocalObject(uint netId)
- {
- if (NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity identity))
+ catch (InvalidOperationException e)
{
- return identity.gameObject;
+ logger.LogException(e);
+ logger.LogError("Could not DestroyAllClientObjects because spawned list was modified during loop, make sure you are not modifying NetworkIdentity.spawned by calling NetworkServer.Destroy or NetworkServer.Spawn in OnDestroy or OnDisable.");
}
- return null;
}
- static void ApplySpawnPayload(NetworkIdentity identity, Vector3 position, Quaternion rotation, Vector3 scale, ArraySegment payload, uint netId)
+ static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage msg)
{
+ if (msg.assetId != Guid.Empty)
+ identity.assetId = msg.assetId;
+
if (!identity.gameObject.activeSelf)
{
identity.gameObject.SetActive(true);
}
// apply local values for VR support
- identity.transform.localPosition = position;
- identity.transform.localRotation = rotation;
- identity.transform.localScale = scale;
+ identity.transform.localPosition = msg.position;
+ identity.transform.localRotation = msg.rotation;
+ identity.transform.localScale = msg.scale;
+ identity.hasAuthority = msg.isOwner;
+ identity.netId = msg.netId;
+
+ if (msg.isLocalPlayer)
+ InternalAddPlayer(identity);
// deserialize components if any payload
// (Count is 0 if there were no components)
- if (payload.Count > 0)
+ if (msg.payload.Count > 0)
{
- NetworkReader payloadReader = NetworkReaderPool.GetReader(payload);
- identity.OnUpdateVars(payloadReader, true);
- NetworkReaderPool.Recycle(payloadReader);
+ using (PooledNetworkReader payloadReader = NetworkReaderPool.GetReader(msg.payload))
+ {
+ identity.OnDeserializeAllSafely(payloadReader, true);
+ }
}
- identity.netId = netId;
- NetworkIdentity.spawned[netId] = identity;
+ NetworkIdentity.spawned[msg.netId] = identity;
// objects spawned as part of initial state are started on a second pass
if (isSpawnFinished)
{
+ identity.NotifyAuthority();
identity.OnStartClient();
- CheckForOwner(identity);
+ CheckForLocalPlayer(identity);
}
}
- internal static void OnSpawnPrefab(NetworkConnection _, SpawnPrefabMessage msg)
+ internal static void OnSpawn(SpawnMessage msg)
{
- if (msg.assetId == Guid.Empty)
+ if (msg.assetId == Guid.Empty && msg.sceneId == 0)
{
- Debug.LogError("OnObjSpawn netId: " + msg.netId + " has invalid asset Id");
+ logger.LogError("OnObjSpawn netId: " + msg.netId + " has invalid asset Id");
return;
}
- if (LogFilter.Debug) Debug.Log("Client spawn handler instantiating [netId:" + msg.netId + " asset ID:" + msg.assetId + " pos:" + msg.position + "]");
+ if (logger.LogEnabled()) logger.Log($"Client spawn handler instantiating netId={msg.netId} assetID={msg.assetId} sceneId={msg.sceneId} pos={msg.position}");
+
+ // was the object already spawned?
+ NetworkIdentity identity = GetExistingObject(msg.netId);
- // owner?
- if (msg.owner)
+ if (identity == null)
{
- OnSpawnMessageForOwner(msg.netId);
+ identity = msg.sceneId == 0 ? SpawnPrefab(msg) : SpawnSceneObject(msg);
}
- if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
+ if (identity == null)
{
- // this object already exists (was in the scene), just apply the update to existing object
- localObject.Reset();
- ApplySpawnPayload(localObject, msg.position, msg.rotation, msg.scale, msg.payload, msg.netId);
+ logger.LogError($"Could not spawn assetId={msg.assetId} scene={msg.sceneId} netId={msg.netId}");
return;
}
+ ApplySpawnPayload(identity, msg);
+ }
+
+ static NetworkIdentity GetExistingObject(uint netid)
+ {
+ NetworkIdentity.spawned.TryGetValue(netid, out NetworkIdentity localObject);
+ return localObject;
+ }
+
+ static NetworkIdentity SpawnPrefab(SpawnMessage msg)
+ {
if (GetPrefab(msg.assetId, out GameObject prefab))
{
GameObject obj = Object.Instantiate(prefab, msg.position, msg.rotation);
- if (LogFilter.Debug)
+ if (logger.LogEnabled())
{
- Debug.Log("Client spawn handler instantiating [netId:" + msg.netId + " asset ID:" + msg.assetId + " pos:" + msg.position + " rotation: " + msg.rotation + "]");
+ logger.Log("Client spawn handler instantiating [netId:" + msg.netId + " asset ID:" + msg.assetId + " pos:" + msg.position + " rotation: " + msg.rotation + "]");
}
- localObject = obj.GetComponent();
- if (localObject == null)
- {
- Debug.LogError("Client object spawned for " + msg.assetId + " does not have a NetworkIdentity");
- return;
- }
- localObject.Reset();
- localObject.pendingOwner = msg.owner;
- ApplySpawnPayload(localObject, msg.position, msg.rotation, msg.scale, msg.payload, msg.netId);
+ return obj.GetComponent();
}
- // lookup registered factory for type:
- else if (spawnHandlers.TryGetValue(msg.assetId, out SpawnDelegate handler))
+ if (spawnHandlers.TryGetValue(msg.assetId, out SpawnHandlerDelegate handler))
{
- GameObject obj = handler(msg.position, msg.assetId);
+ GameObject obj = handler(msg);
if (obj == null)
{
- Debug.LogWarning("Client spawn handler for " + msg.assetId + " returned null");
- return;
- }
- localObject = obj.GetComponent();
- if (localObject == null)
- {
- Debug.LogError("Client object spawned for " + msg.assetId + " does not have a network identity");
- return;
+ logger.LogWarning("Client spawn handler for " + msg.assetId + " returned null");
+ return null;
}
- localObject.Reset();
- localObject.pendingOwner = msg.owner;
- localObject.assetId = msg.assetId;
- ApplySpawnPayload(localObject, msg.position, msg.rotation, msg.scale, msg.payload, msg.netId);
- }
- else
- {
- Debug.LogError("Failed to spawn server object, did you forget to add it to the NetworkManager? assetId=" + msg.assetId + " netId=" + msg.netId);
+ return obj.GetComponent();
}
+ logger.LogError("Failed to spawn server object, did you forget to add it to the NetworkManager? assetId=" + msg.assetId + " netId=" + msg.netId);
+ return null;
}
- internal static void OnSpawnSceneObject(NetworkConnection _, SpawnSceneObjectMessage msg)
+ static NetworkIdentity SpawnSceneObject(SpawnMessage msg)
{
- if (LogFilter.Debug) Debug.Log("Client spawn scene handler instantiating [netId:" + msg.netId + " sceneId:" + msg.sceneId + " pos:" + msg.position);
-
- // owner?
- if (msg.owner)
- {
- OnSpawnMessageForOwner(msg.netId);
- }
-
- if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
- {
- // this object already exists (was in the scene)
- localObject.Reset();
- ApplySpawnPayload(localObject, msg.position, msg.rotation, msg.scale, msg.payload, msg.netId);
- return;
- }
-
NetworkIdentity spawnedId = SpawnSceneObject(msg.sceneId);
if (spawnedId == null)
{
- Debug.LogError("Spawn scene object not found for " + msg.sceneId.ToString("X") + " SpawnableObjects.Count=" + spawnableObjects.Count);
+ logger.LogError("Spawn scene object not found for " + msg.sceneId.ToString("X") + " SpawnableObjects.Count=" + spawnableObjects.Count);
// dump the whole spawnable objects dict for easier debugging
- if (LogFilter.Debug)
+ if (logger.LogEnabled())
{
foreach (KeyValuePair kvp in spawnableObjects)
- Debug.Log("Spawnable: SceneId=" + kvp.Key + " name=" + kvp.Value.name);
+ logger.Log("Spawnable: SceneId=" + kvp.Key + " name=" + kvp.Value.name);
}
-
- return;
}
- if (LogFilter.Debug) Debug.Log("Client spawn for [netId:" + msg.netId + "] [sceneId:" + msg.sceneId + "] obj:" + spawnedId.gameObject.name);
- spawnedId.Reset();
- spawnedId.pendingOwner = msg.owner;
- ApplySpawnPayload(spawnedId, msg.position, msg.rotation, msg.scale, msg.payload, msg.netId);
+ if (logger.LogEnabled()) logger.Log("Client spawn for [netId:" + msg.netId + "] [sceneId:" + msg.sceneId + "] obj:" + spawnedId);
+ return spawnedId;
+ }
+
+ static NetworkIdentity SpawnSceneObject(ulong sceneId)
+ {
+ if (spawnableObjects.TryGetValue(sceneId, out NetworkIdentity identity))
+ {
+ spawnableObjects.Remove(sceneId);
+ return identity;
+ }
+ logger.LogWarning("Could not find scene object with sceneid:" + sceneId.ToString("X"));
+ return null;
}
- internal static void OnObjectSpawnStarted(NetworkConnection _, ObjectSpawnStartedMessage msg)
+ internal static void OnObjectSpawnStarted(ObjectSpawnStartedMessage _)
{
- if (LogFilter.Debug) Debug.Log("SpawnStarted");
+ if (logger.LogEnabled()) logger.Log("SpawnStarted");
PrepareToSpawnSceneObjects();
isSpawnFinished = false;
}
- internal static void OnObjectSpawnFinished(NetworkConnection _, ObjectSpawnFinishedMessage msg)
+ internal static void OnObjectSpawnFinished(ObjectSpawnFinishedMessage _)
{
- if (LogFilter.Debug) Debug.Log("SpawnFinished");
+ logger.Log("SpawnFinished");
// paul: Initialize the objects in the same order as they were initialized
// in the server. This is important if spawned objects
// use data from scene objects
foreach (NetworkIdentity identity in NetworkIdentity.spawned.Values.OrderBy(uv => uv.netId))
{
- if (!identity.isClient)
- {
- identity.OnStartClient();
- CheckForOwner(identity);
- }
+ identity.NotifyAuthority();
+ identity.OnStartClient();
+ CheckForLocalPlayer(identity);
}
isSpawnFinished = true;
}
- internal static void OnObjectHide(NetworkConnection _, ObjectHideMessage msg)
+ internal static void OnObjectHide(ObjectHideMessage msg)
{
DestroyObject(msg.netId);
}
- internal static void OnObjectDestroy(NetworkConnection _, ObjectDestroyMessage msg)
+ internal static void OnObjectDestroy(ObjectDestroyMessage msg)
{
DestroyObject(msg.netId);
}
static void DestroyObject(uint netId)
{
- if (LogFilter.Debug) Debug.Log("ClientScene.OnObjDestroy netId:" + netId);
+ if (logger.LogEnabled()) logger.Log("ClientScene.OnObjDestroy netId:" + netId);
if (NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity localObject) && localObject != null)
{
- localObject.OnNetworkDestroy();
+ localObject.OnStopClient();
if (!InvokeUnSpawnHandler(localObject.assetId, localObject.gameObject))
{
@@ -635,140 +911,96 @@ static void DestroyObject(uint netId)
}
}
NetworkIdentity.spawned.Remove(netId);
- localObject.MarkForReset();
+ localObject.Reset();
}
else
{
- if (LogFilter.Debug) Debug.LogWarning("Did not find target for destroy message for " + netId);
+ if (logger.LogEnabled()) logger.LogWarning("Did not find target for destroy message for " + netId);
}
}
- internal static void OnLocalClientObjectDestroy(NetworkConnection _, ObjectDestroyMessage msg)
+ internal static void OnHostClientObjectDestroy(ObjectDestroyMessage msg)
{
- if (LogFilter.Debug) Debug.Log("ClientScene.OnLocalObjectObjDestroy netId:" + msg.netId);
+ if (logger.LogEnabled()) logger.Log("ClientScene.OnLocalObjectObjDestroy netId:" + msg.netId);
NetworkIdentity.spawned.Remove(msg.netId);
}
- internal static void OnLocalClientObjectHide(NetworkConnection _, ObjectHideMessage msg)
+ internal static void OnHostClientObjectHide(ObjectHideMessage msg)
{
- if (LogFilter.Debug) Debug.Log("ClientScene::OnLocalObjectObjHide netId:" + msg.netId);
+ if (logger.LogEnabled()) logger.Log("ClientScene::OnLocalObjectObjHide netId:" + msg.netId);
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
{
- localObject.OnSetLocalVisibility(false);
+ localObject.OnSetHostVisibility(false);
}
}
- internal static void OnLocalClientSpawnPrefab(NetworkConnection _, SpawnPrefabMessage msg)
+ internal static void OnHostClientSpawn(SpawnMessage msg)
{
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
{
- localObject.OnSetLocalVisibility(true);
- }
- }
+ if (msg.isLocalPlayer)
+ InternalAddPlayer(localObject);
- internal static void OnLocalClientSpawnSceneObject(NetworkConnection _, SpawnSceneObjectMessage msg)
- {
- if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
- {
- localObject.OnSetLocalVisibility(true);
+ localObject.hasAuthority = msg.isOwner;
+ localObject.NotifyAuthority();
+ localObject.OnStartClient();
+ localObject.OnSetHostVisibility(true);
+ CheckForLocalPlayer(localObject);
}
}
- internal static void OnUpdateVarsMessage(NetworkConnection _, UpdateVarsMessage msg)
+ internal static void OnUpdateVarsMessage(UpdateVarsMessage msg)
{
- if (LogFilter.Debug) Debug.Log("ClientScene.OnUpdateVarsMessage " + msg.netId);
+ if (logger.LogEnabled()) logger.Log("ClientScene.OnUpdateVarsMessage " + msg.netId);
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
{
- NetworkReader reader = NetworkReaderPool.GetReader(msg.payload);
- localObject.OnUpdateVars(reader, false);
- NetworkReaderPool.Recycle(reader);
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload))
+ localObject.OnDeserializeAllSafely(networkReader, false);
}
else
{
- Debug.LogWarning("Did not find target for sync message for " + msg.netId + " . Note: this can be completely normal because UDP messages may arrive out of order, so this message might have arrived after a Destroy message.");
+ logger.LogWarning("Did not find target for sync message for " + msg.netId + " . Note: this can be completely normal because UDP messages may arrive out of order, so this message might have arrived after a Destroy message.");
}
}
- internal static void OnRPCMessage(NetworkConnection _, RpcMessage msg)
+ internal static void OnRPCMessage(RpcMessage msg)
{
- if (LogFilter.Debug) Debug.Log("ClientScene.OnRPCMessage hash:" + msg.functionHash + " netId:" + msg.netId);
+ if (logger.LogEnabled()) logger.Log("ClientScene.OnRPCMessage hash:" + msg.functionHash + " netId:" + msg.netId);
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
{
- NetworkReader reader = NetworkReaderPool.GetReader(msg.payload);
- identity.HandleRPC(msg.componentIndex, msg.functionHash, reader);
- NetworkReaderPool.Recycle(reader);
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload))
+ identity.HandleRPC(msg.componentIndex, msg.functionHash, networkReader);
}
}
- internal static void OnSyncEventMessage(NetworkConnection _, SyncEventMessage msg)
+ internal static void OnSyncEventMessage(SyncEventMessage msg)
{
- if (LogFilter.Debug) Debug.Log("ClientScene.OnSyncEventMessage " + msg.netId);
+ if (logger.LogEnabled()) logger.Log("ClientScene.OnSyncEventMessage " + msg.netId);
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
{
- NetworkReader reader = NetworkReaderPool.GetReader(msg.payload);
- identity.HandleSyncEvent(msg.componentIndex, msg.functionHash, reader);
- NetworkReaderPool.Recycle(reader);
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload))
+ identity.HandleSyncEvent(msg.componentIndex, msg.functionHash, networkReader);
}
else
{
- Debug.LogWarning("Did not find target for SyncEvent message for " + msg.netId);
+ logger.LogWarning("Did not find target for SyncEvent message for " + msg.netId);
}
}
- internal static void OnClientAuthority(NetworkConnection _, ClientAuthorityMessage msg)
+ static void CheckForLocalPlayer(NetworkIdentity identity)
{
- if (LogFilter.Debug) Debug.Log("ClientScene.OnClientAuthority for netId: " + msg.netId);
-
- if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
+ if (identity == localPlayer)
{
- identity.HandleClientAuthority(msg.authority);
- }
- }
-
- // called for the one object in the spawn message which is the owner!
- internal static void OnSpawnMessageForOwner(uint netId)
- {
- if (LogFilter.Debug) Debug.Log("ClientScene.OnOwnerMessage - connectionId=" + readyConnection.connectionId + " netId: " + netId);
-
- // is there already an owner that is a different object??
- if (readyConnection.identity != null)
- {
- readyConnection.identity.SetNotLocalPlayer();
- }
-
- if (NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity localObject) && localObject != null)
- {
- // this object already exists
- localObject.connectionToServer = readyConnection;
- localObject.SetLocalPlayer();
- InternalAddPlayer(localObject);
- }
- }
-
- static void CheckForOwner(NetworkIdentity identity)
- {
- if (identity.pendingOwner)
- {
- // found owner, turn into a local player
-
// Set isLocalPlayer to true on this NetworkIdentity and trigger OnStartLocalPlayer in all scripts on the same GO
identity.connectionToServer = readyConnection;
- identity.SetLocalPlayer();
-
- if (LogFilter.Debug) Debug.Log("ClientScene.OnOwnerMessage - player=" + identity.name);
- if (readyConnection.connectionId < 0)
- {
- Debug.LogError("Owner message received on a local client.");
- return;
- }
- InternalAddPlayer(identity);
+ identity.OnStartLocalPlayer();
- identity.pendingOwner = false;
+ if (logger.LogEnabled()) logger.Log("ClientScene.OnOwnerMessage - player=" + identity.name);
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/CustomAttributes.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/CustomAttributes.cs
index 530f98b..65a3885 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/CustomAttributes.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/CustomAttributes.cs
@@ -1,22 +1,14 @@
using System;
-using System.ComponentModel;
using UnityEngine;
namespace Mirror
{
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use NetworkBehaviour.syncInterval field instead. Can be modified in the Inspector too.")]
- [AttributeUsage(AttributeTargets.Class)]
- public class NetworkSettingsAttribute : Attribute
- {
- public float sendInterval = 0.1f;
- }
-
///
/// SyncVars are used to synchronize a variable from the server to all clients automatically.
/// Value must be changed on server, not directly by clients. Hook parameter allows you to define a client-side method to be invoked when the client gets an update from the server.
///
[AttributeUsage(AttributeTargets.Field)]
- public class SyncVarAttribute : Attribute
+ public class SyncVarAttribute : PropertyAttribute
{
public string hook;
}
@@ -28,7 +20,9 @@ public class SyncVarAttribute : Attribute
[AttributeUsage(AttributeTargets.Method)]
public class CommandAttribute : Attribute
{
- public int channel = Channels.DefaultReliable; // this is zero
+ // this is zero
+ public int channel = Channels.DefaultReliable;
+ public bool ignoreAuthority = false;
}
///
@@ -37,7 +31,9 @@ public class CommandAttribute : Attribute
[AttributeUsage(AttributeTargets.Method)]
public class ClientRpcAttribute : Attribute
{
- public int channel = Channels.DefaultReliable; // this is zero
+ // this is zero
+ public int channel = Channels.DefaultReliable;
+ public bool excludeOwner = false;
}
///
@@ -46,7 +42,8 @@ public class ClientRpcAttribute : Attribute
[AttributeUsage(AttributeTargets.Method)]
public class TargetRpcAttribute : Attribute
{
- public int channel = Channels.DefaultReliable; // this is zero
+ // this is zero
+ public int channel = Channels.DefaultReliable;
}
///
@@ -55,7 +52,8 @@ public class TargetRpcAttribute : Attribute
[AttributeUsage(AttributeTargets.Event)]
public class SyncEventAttribute : Attribute
{
- public int channel = Channels.DefaultReliable; // this is zero
+ // this is zero
+ public int channel = Channels.DefaultReliable;
}
///
@@ -90,4 +88,11 @@ public class ClientCallbackAttribute : Attribute { }
/// Converts a string property into a Scene property in the inspector
///
public class SceneAttribute : PropertyAttribute { }
+
+ ///
+ /// Used to show private SyncList in the inspector,
+ /// Use instead of SerializeField for non Serializable types
+ ///
+ [AttributeUsage(AttributeTargets.Field)]
+ public class ShowInInspectorAttribute : Attribute { }
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/FloatBytePacker.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/FloatBytePacker.cs
index 2293d21..26d1cc0 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/FloatBytePacker.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/FloatBytePacker.cs
@@ -1,60 +1,2 @@
-using UnityEngine;
-
-namespace Mirror
-{
- public static class FloatBytePacker
- {
- // ScaleFloatToByte( -1f, -1f, 1f, byte.MinValue, byte.MaxValue) => 0
- // ScaleFloatToByte( 0f, -1f, 1f, byte.MinValue, byte.MaxValue) => 127
- // ScaleFloatToByte(0.5f, -1f, 1f, byte.MinValue, byte.MaxValue) => 191
- // ScaleFloatToByte( 1f, -1f, 1f, byte.MinValue, byte.MaxValue) => 255
- public static byte ScaleFloatToByte(float value, float minValue, float maxValue, byte minTarget, byte maxTarget)
- {
- // note: C# byte - byte => int, hence so many casts
- int targetRange = maxTarget - minTarget; // max byte - min byte only fits into something bigger
- float valueRange = maxValue - minValue;
- float valueRelative = value - minValue;
- return (byte)(minTarget + (byte)(valueRelative/valueRange * targetRange));
- }
-
- // ScaleByteToFloat( 0, byte.MinValue, byte.MaxValue, -1, 1) => -1
- // ScaleByteToFloat(127, byte.MinValue, byte.MaxValue, -1, 1) => -0.003921569
- // ScaleByteToFloat(191, byte.MinValue, byte.MaxValue, -1, 1) => 0.4980392
- // ScaleByteToFloat(255, byte.MinValue, byte.MaxValue, -1, 1) => 1
- public static float ScaleByteToFloat(byte value, byte minValue, byte maxValue, float minTarget, float maxTarget)
- {
- // note: C# byte - byte => int, hence so many casts
- float targetRange = maxTarget - minTarget;
- byte valueRange = (byte)(maxValue - minValue);
- byte valueRelative = (byte)(value - minValue);
- return minTarget + (valueRelative / (float)valueRange * targetRange);
- }
-
- // eulerAngles have 3 floats, putting them into 2 bytes of [x,y],[z,0]
- // would be a waste. instead we compress into 5 bits each => 15 bits.
- // so a ushort.
- public static ushort PackThreeFloatsIntoUShort(float u, float v, float w, float minValue, float maxValue)
- {
- // 5 bits max value = 1+2+4+8+16 = 31 = 0x1F
- byte lower = ScaleFloatToByte(u, minValue, maxValue, 0x00, 0x1F);
- byte middle = ScaleFloatToByte(v, minValue, maxValue, 0x00, 0x1F);
- byte upper = ScaleFloatToByte(w, minValue, maxValue, 0x00, 0x1F);
- ushort combined = (ushort)(upper << 10 | middle << 5 | lower);
- return combined;
- }
-
- // see PackThreeFloatsIntoUShort for explanation
- public static Vector3 UnpackUShortIntoThreeFloats(ushort combined, float minTarget, float maxTarget)
- {
- byte lower = (byte)(combined & 0x1F);
- byte middle = (byte)((combined >> 5) & 0x1F);
- byte upper = (byte)(combined >> 10); // nothing on the left, no & needed
-
- // note: we have to use 4 bits per float, so between 0x00 and 0x0F
- float u = ScaleByteToFloat(lower, 0x00, 0x1F, minTarget, maxTarget);
- float v = ScaleByteToFloat(middle, 0x00, 0x1F, minTarget, maxTarget);
- float w = ScaleByteToFloat(upper, 0x00, 0x1F, minTarget, maxTarget);
- return new Vector3(u, v, w);
- }
- }
-}
+// File Removed 24-Mar-20 - keeping it in here so AssetStore updates overwrite
+// the old one.
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LocalClient.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LocalClient.cs
deleted file mode 100644
index 20db50b..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LocalClient.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-// This file was removed in Mirror 3.4.9
-// The purpose of this file is to get the old file overwritten
-// when users update from the asset store to prevent a flood of errors
-// from having the old file still in the project as a straggler.
-// This file will be dropped from the Asset Store package in May 2019
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LocalClient.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LocalClient.cs.meta
deleted file mode 100644
index 6c073e6..0000000
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LocalClient.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 5c4d04450e91c438385de7300abef1b6
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LocalConnections.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LocalConnections.cs
index 1529085..76607e5 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LocalConnections.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LocalConnections.cs
@@ -5,47 +5,135 @@ namespace Mirror
{
// a server's connection TO a LocalClient.
// sending messages on this connection causes the client's handler function to be invoked directly
- class ULocalConnectionToClient : NetworkConnection
+ class ULocalConnectionToClient : NetworkConnectionToClient
{
- public ULocalConnectionToClient() : base ("localClient")
- {
- // local player always has connectionId == 0
- connectionId = 0;
- }
+ internal ULocalConnectionToServer connectionToServer;
+
+ public ULocalConnectionToClient() : base(LocalConnectionId) { }
+
+ public override string address => "localhost";
internal override bool Send(ArraySegment segment, int channelId = Channels.DefaultReliable)
{
- // LocalConnection doesn't support allocation-free sends yet.
- // previously we allocated in Mirror. now we do it here.
- NetworkWriter writer = NetworkWriterPool.GetWriter();
- writer.WriteBytes(segment.Array, segment.Offset, segment.Count);
- NetworkClient.localClientPacketQueue.Enqueue(writer);
+ connectionToServer.buffer.Write(segment);
+
return true;
}
+
+ // override for host client: always return true.
+ internal override bool IsClientAlive() => true;
+
+ internal void DisconnectInternal()
+ {
+ // set not ready and handle clientscene disconnect in any case
+ // (might be client or host mode here)
+ isReady = false;
+ RemoveObservers();
+ }
+
+ ///
+ /// Disconnects this connection.
+ ///
+ public override void Disconnect()
+ {
+ DisconnectInternal();
+ connectionToServer.DisconnectInternal();
+ }
}
- // a localClient's connection TO a server.
- // send messages on this connection causes the server's handler function to be invoked directly.
- internal class ULocalConnectionToServer : NetworkConnection
+ internal class LocalConnectionBuffer
{
- public ULocalConnectionToServer() : base("localServer")
+ readonly NetworkWriter writer = new NetworkWriter();
+ readonly NetworkReader reader = new NetworkReader(default(ArraySegment));
+ // The buffer is atleast 1500 bytes long. So need to keep track of
+ // packet count to know how many ArraySegments are in the buffer
+ int packetCount;
+
+ public void Write(ArraySegment segment)
{
- // local player always has connectionId == 0
- connectionId = 0;
+ writer.WriteBytesAndSizeSegment(segment);
+ packetCount++;
+
+ // update buffer incase writer's length has changed
+ reader.buffer = writer.ToArraySegment();
}
+ public bool HasPackets()
+ {
+ return packetCount > 0;
+ }
+ public ArraySegment GetNextPacket()
+ {
+ ArraySegment packet = reader.ReadBytesAndSizeSegment();
+ packetCount--;
+
+ return packet;
+ }
+
+ public void ResetBuffer()
+ {
+ writer.Reset();
+ reader.Position = 0;
+ }
+ }
+
+ // a localClient's connection TO a server.
+ // send messages on this connection causes the server's handler function to be invoked directly.
+ internal class ULocalConnectionToServer : NetworkConnectionToServer
+ {
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(ULocalConnectionToClient));
+
+ internal ULocalConnectionToClient connectionToClient;
+ internal readonly LocalConnectionBuffer buffer = new LocalConnectionBuffer();
+
+ public override string address => "localhost";
+
internal override bool Send(ArraySegment segment, int channelId = Channels.DefaultReliable)
{
if (segment.Count == 0)
{
- Debug.LogError("LocalConnection.SendBytes cannot send zero bytes");
+ logger.LogError("LocalConnection.SendBytes cannot send zero bytes");
return false;
}
// handle the server's message directly
- // TODO any way to do this without NetworkServer.localConnection?
- NetworkServer.localConnection.TransportReceive(segment, channelId);
+ connectionToClient.TransportReceive(segment, channelId);
return true;
}
+
+ internal void Update()
+ {
+ // process internal messages so they are applied at the correct time
+ while (buffer.HasPackets())
+ {
+ ArraySegment packet = buffer.GetNextPacket();
+
+ // Treat host player messages exactly like connected client
+ // to avoid deceptive / misleading behavior differences
+ TransportReceive(packet, Channels.DefaultReliable);
+ }
+
+ buffer.ResetBuffer();
+ }
+
+ ///
+ /// Disconnects this connection.
+ ///
+ internal void DisconnectInternal()
+ {
+ // set not ready and handle clientscene disconnect in any case
+ // (might be client or host mode here)
+ isReady = false;
+ ClientScene.HandleClientDisconnect(this);
+ }
+
+ ///
+ /// Disconnects this connection.
+ ///
+ public override void Disconnect()
+ {
+ connectionToClient.DisconnectInternal();
+ DisconnectInternal();
+ }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LogFactory.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LogFactory.cs
new file mode 100644
index 0000000..433d09b
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LogFactory.cs
@@ -0,0 +1 @@
+// File moved to Mirror/Runtime/Logging/LogFactory.cs
\ No newline at end of file
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LogFactory.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LogFactory.cs.meta
new file mode 100644
index 0000000..0715501
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/LogFactory.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 353c7c9e14e82f349b1679112050b196
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging.meta
new file mode 100644
index 0000000..867da74
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 63d647500ca1bfa4a845bc1f4cff9dcc
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs
new file mode 100644
index 0000000..a1b7d22
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs
@@ -0,0 +1,44 @@
+using System;
+using UnityEngine;
+
+namespace Mirror.Logging
+{
+ public class ConsoleColorLogHandler : ILogHandler
+ {
+ readonly bool showExceptionStackTrace;
+
+ public ConsoleColorLogHandler(bool showExceptionStackTrace)
+ {
+ this.showExceptionStackTrace = showExceptionStackTrace;
+ }
+
+ public void LogException(Exception exception, UnityEngine.Object context)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"Exception: {exception.Message}");
+ if (showExceptionStackTrace)
+ {
+ Console.WriteLine($" {exception.StackTrace}");
+ }
+ Console.ResetColor();
+ }
+
+ public void LogFormat(LogType logType, UnityEngine.Object context, string format, params object[] args)
+ {
+ switch (logType)
+ {
+ case LogType.Exception:
+ case LogType.Error:
+ case LogType.Assert:
+ Console.ForegroundColor = ConsoleColor.Red;
+ break;
+ case LogType.Warning:
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ break;
+ }
+
+ Console.WriteLine(string.Format(format, args));
+ Console.ResetColor();
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs.meta
new file mode 100644
index 0000000..329c6eb
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2a9618569c20a504aa86feb5913c70e9
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/EditorLogSettingsLoader.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/EditorLogSettingsLoader.cs
new file mode 100644
index 0000000..8f5c4e4
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/EditorLogSettingsLoader.cs
@@ -0,0 +1,50 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace Mirror.Logging
+{
+#if UNITY_EDITOR
+ public static class EditorLogSettingsLoader
+ {
+ [InitializeOnLoadMethod]
+ static void Init()
+ {
+ // load settings first time LogFactory is used in the editor
+ LoadLogSettingsIntoDictionary();
+ }
+
+ public static void LoadLogSettingsIntoDictionary()
+ {
+ LogSettings settings = FindLogSettings();
+ if (settings != null)
+ {
+ settings.LoadIntoDictionary(LogFactory.loggers);
+ }
+ }
+
+ static LogSettings cache;
+ public static LogSettings FindLogSettings()
+ {
+ if (cache != null)
+ return cache;
+
+ string[] assetGuids = AssetDatabase.FindAssets("t:" + nameof(LogSettings));
+ if (assetGuids.Length == 0)
+ return null;
+
+ string firstGuid = assetGuids[0];
+
+ string path = AssetDatabase.GUIDToAssetPath(firstGuid);
+ cache = AssetDatabase.LoadAssetAtPath(path);
+
+ if (assetGuids.Length > 2)
+ {
+ Debug.LogWarning("Found more than one LogSettings, Delete extra settings. Using first asset found: " + path);
+ }
+ Debug.Assert(cache != null, "Failed to load asset at: " + path);
+
+ return cache;
+ }
+ }
+#endif
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/EditorLogSettingsLoader.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/EditorLogSettingsLoader.cs.meta
new file mode 100644
index 0000000..81b33e9
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/EditorLogSettingsLoader.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a39aa1e48aa54eb4e964f0191c1dcdce
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogFactory.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogFactory.cs
new file mode 100644
index 0000000..24c2b2f
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogFactory.cs
@@ -0,0 +1,100 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Mirror
+{
+ public static class LogFactory
+ {
+ internal static readonly SortedDictionary loggers = new SortedDictionary();
+
+ public static SortedDictionary.ValueCollection AllLoggers => loggers.Values;
+
+ ///
+ /// logHandler used for new loggers
+ ///
+ static ILogHandler defaultLogHandler = Debug.unityLogger;
+
+ ///
+ /// if true sets all log level to LogType.Log
+ ///
+ static bool debugMode = false;
+
+ public static ILogger GetLogger(LogType defaultLogLevel = LogType.Warning)
+ {
+ return GetLogger(typeof(T).Name, defaultLogLevel);
+ }
+
+ public static ILogger GetLogger(System.Type type, LogType defaultLogLevel = LogType.Warning)
+ {
+ return GetLogger(type.Name, defaultLogLevel);
+ }
+
+ public static ILogger GetLogger(string loggerName, LogType defaultLogLevel = LogType.Warning)
+ {
+ if (loggers.TryGetValue(loggerName, out ILogger logger))
+ {
+ return logger;
+ }
+
+ logger = new Logger(defaultLogHandler)
+ {
+ // by default, log warnings and up
+ filterLogType = debugMode ? LogType.Log : defaultLogLevel
+ };
+
+ loggers[loggerName] = logger;
+ return logger;
+ }
+
+ ///
+ /// Makes all log levels LogType.Log, this is so that NetworkManger.showDebugMessages can still be used
+ ///
+ internal static void EnableDebugMode()
+ {
+ debugMode = true;
+
+ foreach (ILogger logger in loggers.Values)
+ {
+ logger.filterLogType = LogType.Log;
+ }
+ }
+
+ ///
+ /// Replacing log handler for all existing loggers and sets defaultLogHandler for new loggers
+ ///
+ ///
+ public static void ReplaceLogHandler(ILogHandler logHandler)
+ {
+ defaultLogHandler = logHandler;
+
+ foreach (ILogger logger in loggers.Values)
+ {
+ logger.logHandler = logHandler;
+ }
+ }
+ }
+
+
+ public static class ILoggerExtensions
+ {
+ public static void LogError(this ILogger logger, object message)
+ {
+ logger.Log(LogType.Error, message);
+ }
+
+ public static void Assert(this ILogger logger, bool condition, string message)
+ {
+ if (!condition)
+ logger.Log(LogType.Assert, message);
+ }
+
+ public static void LogWarning(this ILogger logger, object message)
+ {
+ logger.Log(LogType.Warning, message);
+ }
+
+ public static bool LogEnabled(this ILogger logger) => logger.IsLogTypeAllowed(LogType.Log);
+ public static bool WarnEnabled(this ILogger logger) => logger.IsLogTypeAllowed(LogType.Warning);
+ public static bool ErrorEnabled(this ILogger logger) => logger.IsLogTypeAllowed(LogType.Error);
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogFactory.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogFactory.cs.meta
new file mode 100644
index 0000000..acf3b63
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogFactory.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d06522432d5a44e1587967a4731cd279
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogSettings.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogSettings.cs
new file mode 100644
index 0000000..abd91c1
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogSettings.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Mirror.Logging
+{
+ public class LogSettings : ScriptableObject
+ {
+ public List loglevels = new List();
+
+ [Serializable]
+ public struct LoggerSettings
+ {
+ public string name;
+ public LogType logLevel;
+ }
+ }
+
+ public static class LogSettingsExt
+ {
+ public static void SaveFromDictionary(this LogSettings settings, SortedDictionary dictionary)
+ {
+ if (settings == null)
+ {
+ Debug.LogWarning("Could not SaveFromDictionary because LogSettings were null");
+ return;
+ }
+
+ settings.loglevels.Clear();
+
+ foreach (KeyValuePair kvp in dictionary)
+ {
+ settings.loglevels.Add(new LogSettings.LoggerSettings { name = kvp.Key, logLevel = kvp.Value.filterLogType });
+ }
+
+#if UNITY_EDITOR
+ UnityEditor.EditorUtility.SetDirty(settings);
+#endif
+ }
+
+ public static void LoadIntoDictionary(this LogSettings settings, SortedDictionary dictionary)
+ {
+ if (settings == null)
+ {
+ Debug.LogWarning("Could not LoadIntoDictionary because LogSettings were null");
+ return;
+ }
+
+ foreach (LogSettings.LoggerSettings logLevel in settings.loglevels)
+ {
+ if (dictionary.TryGetValue(logLevel.name, out ILogger logger))
+ {
+ logger.filterLogType = logLevel.logLevel;
+ }
+ else
+ {
+ logger = new Logger(Debug.unityLogger)
+ {
+ filterLogType = logLevel.logLevel
+ };
+
+ dictionary[logLevel.name] = logger;
+ }
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogSettings.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogSettings.cs.meta
new file mode 100644
index 0000000..90c4e4d
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/LogSettings.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 633889a39717fde4fa28dd6b948dfac7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs
new file mode 100644
index 0000000..d41bc2e
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs
@@ -0,0 +1,23 @@
+using UnityEngine;
+
+namespace Mirror.Logging
+{
+ ///
+ /// Used to replace log hanlder with Console Color LogHandler
+ ///
+ [DisallowMultipleComponent]
+ [AddComponentMenu("Network/NetworkHeadlessLogger")]
+ [HelpURL("https://mirror-networking.com/docs/Components/NetworkHeadlessLogger.html")]
+ public class NetworkHeadlessLogger : MonoBehaviour
+ {
+ [SerializeField] bool showExceptionStackTrace = false;
+
+ void Awake()
+ {
+ if (NetworkManager.isHeadless)
+ {
+ LogFactory.ReplaceLogHandler(new ConsoleColorLogHandler(showExceptionStackTrace));
+ }
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs.meta
new file mode 100644
index 0000000..221a61b
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c7627623f2b9fad4484082517cd73e67
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkLogSettings.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkLogSettings.cs
new file mode 100644
index 0000000..cfa6f1c
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkLogSettings.cs
@@ -0,0 +1,46 @@
+using UnityEngine;
+
+namespace Mirror.Logging
+{
+ ///
+ /// Used to load LogSettings in build
+ ///
+ [DisallowMultipleComponent]
+ [AddComponentMenu("Network/NetworkLogSettings")]
+ [HelpURL("https://mirror-networking.com/docs/Components/NetworkLogSettings.html")]
+ public class NetworkLogSettings : MonoBehaviour
+ {
+ [Header("Log Settings Asset")]
+ [SerializeField] internal LogSettings settings;
+
+#if UNITY_EDITOR
+ // called when component is added to GameObject
+ void Reset()
+ {
+ LogSettings existingSettings = EditorLogSettingsLoader.FindLogSettings();
+ if (existingSettings != null)
+ {
+ settings = existingSettings;
+
+ UnityEditor.EditorUtility.SetDirty(this);
+ }
+ }
+#endif
+
+ void Awake()
+ {
+ RefreshDictionary();
+ }
+
+ void OnValidate()
+ {
+ // if settings field is changed
+ RefreshDictionary();
+ }
+
+ void RefreshDictionary()
+ {
+ settings.LoadIntoDictionary(LogFactory.loggers);
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkLogSettings.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkLogSettings.cs.meta
new file mode 100644
index 0000000..2f7ecdf
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Logging/NetworkLogSettings.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ac6e8eccf4b6f4dc7b24c276ef47fde8
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/MessagePacker.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/MessagePacker.cs
index 3200f72..40ba073 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/MessagePacker.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/MessagePacker.cs
@@ -17,6 +17,8 @@ namespace Mirror
// (probably even shorter)
public static class MessagePacker
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(MessagePacker));
+
public static int GetId() where T : IMessageBase
{
// paul: 16 bits is enough to avoid collisions
@@ -30,37 +32,16 @@ public static int GetId(Type type)
return type.FullName.GetStableHashCode() & 0xFFFF;
}
- // pack message before sending
- // -> NetworkWriter passed as arg so that we can use .ToArraySegment
- // and do an allocation free send before recycling it.
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use Pack instead")]
- public static byte[] PackMessage(int msgType, MessageBase msg)
- {
- NetworkWriter writer = NetworkWriterPool.GetWriter();
- try
- {
- // write message type
- writer.WriteInt16((short)msgType);
-
- // serialize message into writer
- msg.Serialize(writer);
-
- // return byte[]
- return writer.ToArray();
- }
- finally
- {
- NetworkWriterPool.Recycle(writer);
- }
- }
-
// pack message before sending
// -> NetworkWriter passed as arg so that we can use .ToArraySegment
// and do an allocation free send before recycling it.
public static void Pack(T message, NetworkWriter writer) where T : IMessageBase
{
- // write message type
- int msgType = GetId(typeof(T));
+ // if it is a value type, just use typeof(T) to avoid boxing
+ // this works because value types cannot be derived
+ // if it is a reference type (for example IMessageBase),
+ // ask the message for the real type
+ int msgType = GetId(default(T) != null ? typeof(T) : message.GetType());
writer.WriteUInt16((ushort)msgType);
// serialize message into writer
@@ -73,31 +54,31 @@ public static void Pack(T message, NetworkWriter writer) where T : IMessageBa
[EditorBrowsable(EditorBrowsableState.Never)]
public static byte[] Pack(T message) where T : IMessageBase
{
- NetworkWriter writer = NetworkWriterPool.GetWriter();
-
- Pack(message, writer);
- byte[] data = writer.ToArray();
-
- NetworkWriterPool.Recycle(writer);
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
+ {
+ Pack(message, writer);
+ byte[] data = writer.ToArray();
- return data;
+ return data;
+ }
}
// unpack a message we received
public static T Unpack(byte[] data) where T : IMessageBase, new()
{
- NetworkReader reader = NetworkReaderPool.GetReader(data);
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(data))
+ {
+ int msgType = GetId();
- int msgType = GetId();
+ int id = networkReader.ReadUInt16();
+ if (id != msgType)
+ throw new FormatException("Invalid message, could not unpack " + typeof(T).FullName);
- int id = reader.ReadUInt16();
- if (id != msgType)
- throw new FormatException("Invalid message, could not unpack " + typeof(T).FullName);
+ T message = new T();
+ message.Deserialize(networkReader);
- T message = typeof(T).IsValueType ? default : new T();
- message.Deserialize(reader);
- NetworkReaderPool.Recycle(reader);
- return message;
+ return message;
+ }
}
// unpack message after receiving
@@ -119,7 +100,10 @@ public static bool UnpackMessage(NetworkReader messageReader, out int msgType)
}
}
- internal static NetworkMessageDelegate MessageHandler(Action handler, bool requireAuthenication) where T : IMessageBase, new() => networkMessage =>
+ internal static NetworkMessageDelegate MessageHandler(Action handler, bool requireAuthenication)
+ where T : IMessageBase, new()
+ where C : NetworkConnection
+ => (conn, reader, channelId) =>
{
// protect against DOS attacks if attackers try to send invalid
// data packets to crash the server/client. there are a thousand
@@ -136,29 +120,32 @@ public static bool UnpackMessage(NetworkReader messageReader, out int msgType)
T message = default;
try
{
- if (requireAuthenication && !networkMessage.conn.isAuthenticated)
+ if (requireAuthenication && !conn.isAuthenticated)
{
// message requires authentication, but the connection was not authenticated
- Debug.LogWarning($"Closing connection: {networkMessage.conn.connectionId}. Received message {typeof(T)} that required authentication, but the user has not authenticated yet");
- networkMessage.conn.Disconnect();
+ logger.LogWarning($"Closing connection: {conn}. Received message {typeof(T)} that required authentication, but the user has not authenticated yet");
+ conn.Disconnect();
return;
}
- message = networkMessage.ReadMessage();
+ // if it is a value type, just use defult(T)
+ // otherwise allocate a new instance
+ message = default(T) != null ? default(T) : new T();
+ message.Deserialize(reader);
}
catch (Exception exception)
{
- Debug.LogError("Closed connection: " + networkMessage.conn.connectionId + ". This can happen if the other side accidentally (or an attacker intentionally) sent invalid data. Reason: " + exception);
- networkMessage.conn.Disconnect();
+ logger.LogError("Closed connection: " + conn + ". This can happen if the other side accidentally (or an attacker intentionally) sent invalid data. Reason: " + exception);
+ conn.Disconnect();
return;
}
finally
{
// TODO: Figure out the correct channel
- NetworkDiagnostics.OnReceive(message, networkMessage.channelId, networkMessage.reader.Length);
+ NetworkDiagnostics.OnReceive(message, channelId, reader.Length);
}
- handler(networkMessage.conn, message);
+ handler((C)conn, message);
};
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Messages.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Messages.cs
index 6d2478c..57fef86 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Messages.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Messages.cs
@@ -1,6 +1,5 @@
using System;
using UnityEngine;
-using UnityEngine.SceneManagement;
namespace Mirror
{
@@ -20,144 +19,24 @@ public virtual void Deserialize(NetworkReader reader) { }
public virtual void Serialize(NetworkWriter writer) { }
}
- #region General Typed Messages
- public class StringMessage : MessageBase
- {
- public string value;
-
- public StringMessage() { }
-
- public StringMessage(string v)
- {
- value = v;
- }
-
- public override void Deserialize(NetworkReader reader)
- {
- value = reader.ReadString();
- }
-
- public override void Serialize(NetworkWriter writer)
- {
- writer.WriteString(value);
- }
- }
-
- public class ByteMessage : MessageBase
- {
- public byte value;
-
- public ByteMessage() { }
-
- public ByteMessage(byte v)
- {
- value = v;
- }
-
- public override void Deserialize(NetworkReader reader)
- {
- value = reader.ReadByte();
- }
-
- public override void Serialize(NetworkWriter writer)
- {
- writer.WriteByte(value);
- }
- }
-
- public class BytesMessage : MessageBase
- {
- public byte[] value;
-
- public BytesMessage() { }
-
- public BytesMessage(byte[] v)
- {
- value = v;
- }
-
- public override void Deserialize(NetworkReader reader)
- {
- value = reader.ReadBytesAndSize();
- }
-
- public override void Serialize(NetworkWriter writer)
- {
- writer.WriteBytesAndSize(value);
- }
- }
-
- public class IntegerMessage : MessageBase
- {
- public int value;
-
- public IntegerMessage() { }
-
- public IntegerMessage(int v)
- {
- value = v;
- }
-
- public override void Deserialize(NetworkReader reader)
- {
- value = reader.ReadPackedInt32();
- }
-
- public override void Serialize(NetworkWriter writer)
- {
- writer.WritePackedInt32(value);
- }
- }
-
- public class DoubleMessage : MessageBase
- {
- public double value;
-
- public DoubleMessage() { }
-
- public DoubleMessage(double v)
- {
- value = v;
- }
-
- public override void Deserialize(NetworkReader reader)
- {
- value = reader.ReadDouble();
- }
-
- public override void Serialize(NetworkWriter writer)
- {
- writer.WriteDouble(value);
- }
- }
-
- public class EmptyMessage : MessageBase
- {
- public override void Deserialize(NetworkReader reader) { }
-
- public override void Serialize(NetworkWriter writer) { }
- }
- #endregion
-
#region Public System Messages
-
public struct ErrorMessage : IMessageBase
{
- public byte error;
+ public byte value;
public ErrorMessage(byte v)
{
- error = v;
+ value = v;
}
public void Deserialize(NetworkReader reader)
{
- error = reader.ReadByte();
+ value = reader.ReadByte();
}
public void Serialize(NetworkWriter writer)
{
- writer.WriteByte(error);
+ writer.WriteByte(value);
}
}
@@ -177,31 +56,16 @@ public void Serialize(NetworkWriter writer) { }
public struct AddPlayerMessage : IMessageBase
{
- ///
- /// Obsolete: Create your own message instead. See Custom Players
- ///
- [Obsolete("Create your own message instead. See https://mirror-networking.com/docs/Guides/GameObjects/SpawnPlayerCustom.html")]
- public byte[] value;
-
- ///
- /// Obsolete: Create your own message instead. See Custom Players
- ///
- [Obsolete("Create your own message instead. See https://mirror-networking.com/docs/Guides/GameObjects/SpawnPlayerCustom.html")]
- public void Deserialize(NetworkReader reader)
- {
- value = reader.ReadBytesAndSize();
- }
+ public void Deserialize(NetworkReader reader) { }
- ///
- /// Obsolete: Create your own message instead. See Custom Players
- ///
- [Obsolete("Create your own message instead. See https://mirror-networking.com/docs/Guides/GameObjects/SpawnPlayerCustom.html")]
- public void Serialize(NetworkWriter writer)
- {
- writer.WriteBytesAndSize(value);
- }
+ public void Serialize(NetworkWriter writer) { }
}
+ // Deprecated 5/2/2020
+ ///
+ /// Obsolete: Removed as a security risk. Use NetworkServer.RemovePlayerForConnection instead.
+ ///
+ [Obsolete("Removed as a security risk. Use NetworkServer.RemovePlayerForConnection(NetworkConnection conn, bool keepAuthority = false) instead")]
public struct RemovePlayerMessage : IMessageBase
{
public void Deserialize(NetworkReader reader) { }
@@ -226,18 +90,22 @@ public void Serialize(NetworkWriter writer) { }
public struct SceneMessage : IMessageBase
{
public string sceneName;
- public SceneOperation sceneOperation; // Normal = 0, LoadAdditive = 1, UnloadAdditive = 2
+ // Normal = 0, LoadAdditive = 1, UnloadAdditive = 2
+ public SceneOperation sceneOperation;
+ public bool customHandling;
public void Deserialize(NetworkReader reader)
{
sceneName = reader.ReadString();
sceneOperation = (SceneOperation)reader.ReadByte();
+ customHandling = reader.ReadBoolean();
}
public void Serialize(NetworkWriter writer)
{
writer.WriteString(sceneName);
writer.WriteByte((byte)sceneOperation);
+ writer.WriteBoolean(customHandling);
}
}
@@ -264,7 +132,8 @@ public void Deserialize(NetworkReader reader)
{
netId = reader.ReadPackedUInt32();
componentIndex = (int)reader.ReadPackedUInt32();
- functionHash = reader.ReadInt32(); // hash is always 4 full bytes, WritePackedInt would send 1 extra byte here
+ // hash is always 4 full bytes, WritePackedInt would send 1 extra byte here
+ functionHash = reader.ReadInt32();
payload = reader.ReadBytesAndSizeSegment();
}
@@ -290,7 +159,8 @@ public void Deserialize(NetworkReader reader)
{
netId = reader.ReadPackedUInt32();
componentIndex = (int)reader.ReadPackedUInt32();
- functionHash = reader.ReadInt32(); // hash is always 4 full bytes, WritePackedInt would send 1 extra byte here
+ // hash is always 4 full bytes, WritePackedInt would send 1 extra byte here
+ functionHash = reader.ReadInt32();
payload = reader.ReadBytesAndSizeSegment();
}
@@ -316,7 +186,8 @@ public void Deserialize(NetworkReader reader)
{
netId = reader.ReadPackedUInt32();
componentIndex = (int)reader.ReadPackedUInt32();
- functionHash = reader.ReadInt32(); // hash is always 4 full bytes, WritePackedInt would send 1 extra byte here
+ // hash is always 4 full bytes, WritePackedInt would send 1 extra byte here
+ functionHash = reader.ReadInt32();
payload = reader.ReadBytesAndSizeSegment();
}
@@ -331,58 +202,57 @@ public void Serialize(NetworkWriter writer)
#endregion
#region Internal System Messages
- public struct SpawnPrefabMessage : IMessageBase
- {
- public uint netId;
- public bool owner;
- public Guid assetId;
- public Vector3 position;
- public Quaternion rotation;
- public Vector3 scale;
- // the serialized component data
- // -> ArraySegment to avoid unnecessary allocations
- public ArraySegment payload;
-
- public void Deserialize(NetworkReader reader)
- {
- netId = reader.ReadPackedUInt32();
- owner = reader.ReadBoolean();
- assetId = reader.ReadGuid();
- position = reader.ReadVector3();
- rotation = reader.ReadQuaternion();
- scale = reader.ReadVector3();
- payload = reader.ReadBytesAndSizeSegment();
- }
-
- public void Serialize(NetworkWriter writer)
- {
- writer.WritePackedUInt32(netId);
- writer.WriteBoolean(owner);
- writer.WriteGuid(assetId);
- writer.WriteVector3(position);
- writer.WriteQuaternion(rotation);
- writer.WriteVector3(scale);
- writer.WriteBytesAndSizeSegment(payload);
- }
- }
-
- public struct SpawnSceneObjectMessage : IMessageBase
+ public struct SpawnMessage : IMessageBase
{
+ ///
+ /// netId of new or existing object
+ ///
public uint netId;
- public bool owner;
+ ///
+ /// Is the spawning object the local player. Sets ClientScene.localPlayer
+ ///
+ public bool isLocalPlayer;
+ ///
+ /// Sets hasAuthority on the spawned object
+ ///
+ public bool isOwner;
+ ///
+ /// The id of the scene object to spawn
+ ///
public ulong sceneId;
+ ///
+ /// The id of the prefab to spawn
+ /// If sceneId != 0 then it is used instead of assetId
+ ///
+ public Guid assetId;
+ ///
+ /// Local position
+ ///
public Vector3 position;
+ ///
+ /// Local rotation
+ ///
public Quaternion rotation;
+ ///
+ /// Local scale
+ ///
public Vector3 scale;
- // the serialized component data
- // -> ArraySegment to avoid unnecessary allocations
+ ///
+ /// The serialized component data
+ /// ArraySegment to avoid unnecessary allocations
+ ///
public ArraySegment payload;
public void Deserialize(NetworkReader reader)
{
netId = reader.ReadPackedUInt32();
- owner = reader.ReadBoolean();
- sceneId = reader.ReadUInt64();
+ isLocalPlayer = reader.ReadBoolean();
+ isOwner = reader.ReadBoolean();
+ sceneId = reader.ReadPackedUInt64();
+ if (sceneId == 0)
+ {
+ assetId = reader.ReadGuid();
+ }
position = reader.ReadVector3();
rotation = reader.ReadQuaternion();
scale = reader.ReadVector3();
@@ -392,8 +262,13 @@ public void Deserialize(NetworkReader reader)
public void Serialize(NetworkWriter writer)
{
writer.WritePackedUInt32(netId);
- writer.WriteBoolean(owner);
- writer.WriteUInt64(sceneId);
+ writer.WriteBoolean(isLocalPlayer);
+ writer.WriteBoolean(isOwner);
+ writer.WritePackedUInt64(sceneId);
+ if (sceneId == 0)
+ {
+ writer.WriteGuid(assetId);
+ }
writer.WriteVector3(position);
writer.WriteQuaternion(rotation);
writer.WriteVector3(scale);
@@ -445,24 +320,6 @@ public void Serialize(NetworkWriter writer)
}
}
- public struct ClientAuthorityMessage : IMessageBase
- {
- public uint netId;
- public bool authority;
-
- public void Deserialize(NetworkReader reader)
- {
- netId = reader.ReadPackedUInt32();
- authority = reader.ReadBoolean();
- }
-
- public void Serialize(NetworkWriter writer)
- {
- writer.WritePackedUInt32(netId);
- writer.WriteBoolean(authority);
- }
- }
-
public struct UpdateVarsMessage : IMessageBase
{
public uint netId;
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Mirror.asmdef b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Mirror.asmdef
index 4f3dbbd..c616ae7 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Mirror.asmdef
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/Mirror.asmdef
@@ -1,8 +1,15 @@
{
"name": "Mirror",
- "references": [],
+ "references": [
+ "Mirror.CompilerSymbols",
+ "Ninja.WebSockets"
+ ],
"optionalUnityReferences": [],
"includePlatforms": [],
"excludePlatforms": [],
- "allowUnsafeCode": false
+ "allowUnsafeCode": false,
+ "overrideReferences": false,
+ "precompiledReferences": [],
+ "autoReferenced": true,
+ "defineConstraints": []
}
\ No newline at end of file
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkAuthenticator.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkAuthenticator.cs
index 2c673ff..f35d7fe 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkAuthenticator.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkAuthenticator.cs
@@ -35,7 +35,7 @@ public abstract class NetworkAuthenticator : MonoBehaviour
/// Called on server from StartServer to initialize the Authenticator
/// Server message handlers should be registered in this method.
///
- public virtual void OnStartServer() {}
+ public virtual void OnStartServer() { }
// This will get more code in the near future
internal void OnServerAuthenticateInternal(NetworkConnection conn)
@@ -57,7 +57,7 @@ internal void OnServerAuthenticateInternal(NetworkConnection conn)
/// Called on client from StartClient to initialize the Authenticator
/// Client message handlers should be registered in this method.
///
- public virtual void OnStartClient() {}
+ public virtual void OnStartClient() { }
// This will get more code in the near future
internal void OnClientAuthenticateInternal(NetworkConnection conn)
@@ -76,7 +76,7 @@ internal void OnClientAuthenticateInternal(NetworkConnection conn)
void OnValidate()
{
#if UNITY_EDITOR
- // automatically assign NetworkManager field if we add this to NetworkManager
+ // automatically assign authenticator field if we add this to NetworkManager
NetworkManager manager = GetComponent();
if (manager != null && manager.authenticator == null)
{
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkBehaviour.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkBehaviour.cs
index c56b8eb..22f1fae 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkBehaviour.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkBehaviour.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
+using Mirror.RemoteCalls;
using UnityEngine;
namespace Mirror
@@ -18,10 +19,13 @@ public enum SyncMode { Observers, Owner }
/// The NetworkBehaviour component requires a NetworkIdentity on the game object. There can be multiple NetworkBehaviours on a single game object. For an object with sub-components in a hierarchy, the NetworkIdentity must be on the root object, and NetworkBehaviour scripts must also be on the root object.
/// Some of the built-in components of the networking system are derived from NetworkBehaviour, including NetworkTransport, NetworkAnimator and NetworkProximityChecker.
///
- [RequireComponent(typeof(NetworkIdentity))]
[AddComponentMenu("")]
- public class NetworkBehaviour : MonoBehaviour
+ [RequireComponent(typeof(NetworkIdentity))]
+ [HelpURL("https://mirror-networking.com/docs/Guides/NetworkBehaviour.html")]
+ public abstract class NetworkBehaviour : MonoBehaviour
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkBehaviour));
+
internal float lastSyncTime;
// hidden because NetworkBehaviourInspector shows it only if has OnSerialize.
@@ -34,13 +38,11 @@ public class NetworkBehaviour : MonoBehaviour
///
/// sync interval for OnSerialize (in seconds)
///
+ [Tooltip("Time in seconds until next change is synchronized to the client. '0' means send immediately if changed. '0.5' means only send changes every 500ms.\n(This is for state synchronization like SyncVars, SyncLists, OnSerialize. Not for Cmds, Rpcs, etc.)")]
+ // [0,2] should be enough. anything >2s is too laggy anyway.
+ [Range(0, 2)]
[HideInInspector] public float syncInterval = 0.1f;
- ///
- /// This value is set on the NetworkIdentity and is accessible here for convenient access for scripts.
- ///
- public bool localPlayerAuthority => netIdentity.localPlayerAuthority;
-
///
/// Returns true if this object is active on an active server.
/// This is only true if the object has been spawned. This is different from NetworkServer.active, which is true if the server itself is active rather than this object being active.
@@ -70,7 +72,7 @@ public class NetworkBehaviour : MonoBehaviour
///
/// This returns true if this object is the authoritative version of the object in the distributed network application.
- /// The localPlayerAuthority value on the NetworkIdentity determines how authority is determined. For most objects, authority is held by the server / host. For objects with localPlayerAuthority set, authority is held by the client of that player.
+ /// The NetworkIdentity.hasAuthority value on the NetworkIdentity determines how authority is determined. For most objects, authority is held by the server. For objects with NetworkIdentity.hasAuthority set, authority is held by the client of that player.
///
public bool hasAuthority => netIdentity.hasAuthority;
@@ -81,7 +83,7 @@ public class NetworkBehaviour : MonoBehaviour
public uint netId => netIdentity.netId;
///
- /// The NetworkConnection associated with this NetworkIdentity. This is only valid for player objects on the server.
+ /// The NetworkConnection associated with this NetworkIdentity. This is only valid for player objects on the client.
///
public NetworkConnection connectionToServer => netIdentity.connectionToServer;
@@ -106,12 +108,6 @@ protected void setSyncVarHookGuard(ulong dirtyBit, bool value)
syncVarHookGuard &= ~dirtyBit;
}
- ///
- /// Obsolete: Use instead.
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use syncObjects instead.")]
- protected List m_SyncObjects => syncObjects;
-
///
/// objects that can synchronize themselves, such as synclists
///
@@ -135,7 +131,7 @@ public NetworkIdentity netIdentity
}
if (netIdentityCache == null)
{
- Debug.LogError("There is no NetworkIdentity on " + name + ". Please add one.");
+ logger.LogError("There is no NetworkIdentity on " + name + ". Please add one.");
}
return netIdentityCache;
}
@@ -157,7 +153,7 @@ public int ComponentIndex
}
// this should never happen
- Debug.LogError("Could not find component in GameObject. You should not add/remove components in networked objects dynamically", this);
+ logger.LogError("Could not find component in GameObject. You should not add/remove components in networked objects dynamically", this);
return -1;
}
@@ -172,39 +168,27 @@ protected void InitSyncObject(SyncObject syncObject)
}
#region Commands
-
- static int GetMethodHash(Type invokeClass, string methodName)
- {
- // (invokeClass + ":" + cmdName).GetStableHashCode() would cause allocations.
- // so hash1 + hash2 is better.
- unchecked
- {
- int hash = invokeClass.FullName.GetStableHashCode();
- return hash * 503 + methodName.GetStableHashCode();
- }
- }
-
[EditorBrowsable(EditorBrowsableState.Never)]
- protected void SendCommandInternal(Type invokeClass, string cmdName, NetworkWriter writer, int channelId)
+ protected void SendCommandInternal(Type invokeClass, string cmdName, NetworkWriter writer, int channelId, bool ignoreAuthority = false)
{
// this was in Weaver before
// NOTE: we could remove this later to allow calling Cmds on Server
// to avoid Wrapper functions. a lot of people requested this.
if (!NetworkClient.active)
{
- Debug.LogError("Command Function " + cmdName + " called on server without an active client.");
+ logger.LogError("Command Function " + cmdName + " called on server without an active client.");
return;
}
// local players can always send commands, regardless of authority, other objects must have authority.
- if (!(isLocalPlayer || hasAuthority))
+ if (!(ignoreAuthority || isLocalPlayer || hasAuthority))
{
- Debug.LogWarning("Trying to send command for object without authority.");
+ logger.LogWarning($"Trying to send command for object without authority. {invokeClass.ToString()}.{cmdName}");
return;
}
if (ClientScene.readyConnection == null)
{
- Debug.LogError("Send command attempted with no client running [client=" + connectionToServer + "].");
+ logger.LogError("Send command attempted with no client running [client=" + connectionToServer + "].");
return;
}
@@ -213,8 +197,10 @@ protected void SendCommandInternal(Type invokeClass, string cmdName, NetworkWrit
{
netId = netId,
componentIndex = ComponentIndex,
- functionHash = GetMethodHash(invokeClass, cmdName), // type+func so Inventory.RpcUse != Equipment.RpcUse
- payload = writer.ToArraySegment() // segment to avoid reader allocations
+ // type+func so Inventory.RpcUse != Equipment.RpcUse
+ functionHash = RemoteCallHelper.GetMethodHash(invokeClass, cmdName),
+ // segment to avoid reader allocations
+ payload = writer.ToArraySegment()
};
ClientScene.readyConnection.Send(message, channelId);
@@ -229,24 +215,24 @@ protected void SendCommandInternal(Type invokeClass, string cmdName, NetworkWrit
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual bool InvokeCommand(int cmdHash, NetworkReader reader)
{
- return InvokeHandlerDelegate(cmdHash, MirrorInvokeType.Command, reader);
+ return RemoteCallHelper.InvokeHandlerDelegate(cmdHash, MirrorInvokeType.Command, reader, this);
}
#endregion
#region Client RPCs
[EditorBrowsable(EditorBrowsableState.Never)]
- protected void SendRPCInternal(Type invokeClass, string rpcName, NetworkWriter writer, int channelId)
+ protected void SendRPCInternal(Type invokeClass, string rpcName, NetworkWriter writer, int channelId, bool excludeOwner)
{
// this was in Weaver before
if (!NetworkServer.active)
{
- Debug.LogError("RPC Function " + rpcName + " called on Client.");
+ logger.LogError("RPC Function " + rpcName + " called on Client.");
return;
}
// This cannot use NetworkServer.active, as that is not specific to this object.
if (!isServer)
{
- Debug.LogWarning("ClientRpc " + rpcName + " called on un-spawned object: " + name);
+ logger.LogWarning("ClientRpc " + rpcName + " called on un-spawned object: " + name);
return;
}
@@ -255,11 +241,16 @@ protected void SendRPCInternal(Type invokeClass, string rpcName, NetworkWriter w
{
netId = netId,
componentIndex = ComponentIndex,
- functionHash = GetMethodHash(invokeClass, rpcName), // type+func so Inventory.RpcUse != Equipment.RpcUse
- payload = writer.ToArraySegment() // segment to avoid reader allocations
+ // type+func so Inventory.RpcUse != Equipment.RpcUse
+ functionHash = RemoteCallHelper.GetMethodHash(invokeClass, rpcName),
+ // segment to avoid reader allocations
+ payload = writer.ToArraySegment()
};
- NetworkServer.SendToReady(netIdentity, message, channelId);
+ // The public facing parameter is excludeOwner in [ClientRpc]
+ // so we negate it here to logically align with SendToReady.
+ bool includeOwner = !excludeOwner;
+ NetworkServer.SendToReady(netIdentity, message, includeOwner, channelId);
}
[EditorBrowsable(EditorBrowsableState.Never)]
@@ -268,7 +259,7 @@ protected void SendTargetRPCInternal(NetworkConnection conn, Type invokeClass, s
// this was in Weaver before
if (!NetworkServer.active)
{
- Debug.LogError("TargetRPC Function " + rpcName + " called on client.");
+ logger.LogError("TargetRPC Function " + rpcName + " called on client.");
return;
}
// connection parameter is optional. assign if null.
@@ -277,15 +268,15 @@ protected void SendTargetRPCInternal(NetworkConnection conn, Type invokeClass, s
conn = connectionToClient;
}
// this was in Weaver before
- if (conn is ULocalConnectionToServer)
+ if (conn is NetworkConnectionToServer)
{
- Debug.LogError("TargetRPC Function " + rpcName + " called on connection to server");
+ logger.LogError("TargetRPC Function " + rpcName + " called on connection to server");
return;
}
// This cannot use NetworkServer.active, as that is not specific to this object.
if (!isServer)
{
- Debug.LogWarning("TargetRpc " + rpcName + " called on un-spawned object: " + name);
+ logger.LogWarning("TargetRpc " + rpcName + " called on un-spawned object: " + name);
return;
}
@@ -294,8 +285,10 @@ protected void SendTargetRPCInternal(NetworkConnection conn, Type invokeClass, s
{
netId = netId,
componentIndex = ComponentIndex,
- functionHash = GetMethodHash(invokeClass, rpcName), // type+func so Inventory.RpcUse != Equipment.RpcUse
- payload = writer.ToArraySegment() // segment to avoid reader allocations
+ // type+func so Inventory.RpcUse != Equipment.RpcUse
+ functionHash = RemoteCallHelper.GetMethodHash(invokeClass, rpcName),
+ // segment to avoid reader allocations
+ payload = writer.ToArraySegment()
};
conn.Send(message, channelId);
@@ -310,7 +303,7 @@ protected void SendTargetRPCInternal(NetworkConnection conn, Type invokeClass, s
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual bool InvokeRPC(int rpcHash, NetworkReader reader)
{
- return InvokeHandlerDelegate(rpcHash, MirrorInvokeType.ClientRpc, reader);
+ return RemoteCallHelper.InvokeHandlerDelegate(rpcHash, MirrorInvokeType.ClientRpc, reader, this);
}
#endregion
@@ -320,7 +313,7 @@ protected void SendEventInternal(Type invokeClass, string eventName, NetworkWrit
{
if (!NetworkServer.active)
{
- Debug.LogWarning("SendEvent no server?");
+ logger.LogWarning("SendEvent no server?");
return;
}
@@ -329,8 +322,10 @@ protected void SendEventInternal(Type invokeClass, string eventName, NetworkWrit
{
netId = netId,
componentIndex = ComponentIndex,
- functionHash = GetMethodHash(invokeClass, eventName), // type+func so Inventory.RpcUse != Equipment.RpcUse
- payload = writer.ToArraySegment() // segment to avoid reader allocations
+ // type+func so Inventory.RpcUse != Equipment.RpcUse
+ functionHash = RemoteCallHelper.GetMethodHash(invokeClass, eventName),
+ // segment to avoid reader allocations
+ payload = writer.ToArraySegment()
};
NetworkServer.SendToReady(netIdentity, message, channelId);
@@ -345,119 +340,35 @@ protected void SendEventInternal(Type invokeClass, string eventName, NetworkWrit
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual bool InvokeSyncEvent(int eventHash, NetworkReader reader)
{
- return InvokeHandlerDelegate(eventHash, MirrorInvokeType.SyncEvent, reader);
+ return RemoteCallHelper.InvokeHandlerDelegate(eventHash, MirrorInvokeType.SyncEvent, reader, this);
}
#endregion
- #region Code Gen Path Helpers
- ///
- /// Delegate for Command functions.
- ///
- ///
- ///
- public delegate void CmdDelegate(NetworkBehaviour obj, NetworkReader reader);
-
- protected class Invoker
- {
- public MirrorInvokeType invokeType;
- public Type invokeClass;
- public CmdDelegate invokeFunction;
- }
-
- static readonly Dictionary cmdHandlerDelegates = new Dictionary();
+ #region Helpers
- // helper function register a Command/Rpc/SyncEvent delegate
+ // helper function for [SyncVar] GameObjects.
+ // IMPORTANT: keep as 'protected', not 'internal', otherwise Weaver
+ // can't resolve it
[EditorBrowsable(EditorBrowsableState.Never)]
- protected static void RegisterDelegate(Type invokeClass, string cmdName, MirrorInvokeType invokerType, CmdDelegate func)
+ protected bool SyncVarGameObjectEqual(GameObject newGameObject, uint netIdField)
{
- int cmdHash = GetMethodHash(invokeClass, cmdName); // type+func so Inventory.RpcUse != Equipment.RpcUse
-
- if (cmdHandlerDelegates.ContainsKey(cmdHash))
+ uint newNetId = 0;
+ if (newGameObject != null)
{
- // something already registered this hash
- Invoker oldInvoker = cmdHandlerDelegates[cmdHash];
- if (oldInvoker.invokeClass == invokeClass && oldInvoker.invokeType == invokerType && oldInvoker.invokeFunction == func)
+ NetworkIdentity identity = newGameObject.GetComponent();
+ if (identity != null)
{
- // it's all right, it was the same function
- return;
+ newNetId = identity.netId;
+ if (newNetId == 0)
+ {
+ logger.LogWarning("SetSyncVarGameObject GameObject " + newGameObject + " has a zero netId. Maybe it is not spawned yet?");
+ }
}
-
- Debug.LogError($"Function {oldInvoker.invokeClass}.{oldInvoker.invokeFunction.GetMethodName()} and {invokeClass}.{oldInvoker.invokeFunction.GetMethodName()} have the same hash. Please rename one of them");
}
- Invoker invoker = new Invoker
- {
- invokeType = invokerType,
- invokeClass = invokeClass,
- invokeFunction = func
- };
- cmdHandlerDelegates[cmdHash] = invoker;
- if (LogFilter.Debug) Debug.Log("RegisterDelegate hash:" + cmdHash + " invokerType: " + invokerType + " method:" + func.GetMethodName());
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- protected static void RegisterCommandDelegate(Type invokeClass, string cmdName, CmdDelegate func)
- {
- RegisterDelegate(invokeClass, cmdName, MirrorInvokeType.Command, func);
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- protected static void RegisterRpcDelegate(Type invokeClass, string rpcName, CmdDelegate func)
- {
- RegisterDelegate(invokeClass, rpcName, MirrorInvokeType.ClientRpc, func);
- }
-
- [EditorBrowsable(EditorBrowsableState.Never)]
- protected static void RegisterEventDelegate(Type invokeClass, string eventName, CmdDelegate func)
- {
- RegisterDelegate(invokeClass, eventName, MirrorInvokeType.SyncEvent, func);
- }
-
- static bool GetInvokerForHash(int cmdHash, MirrorInvokeType invokeType, out Invoker invoker)
- {
- if (cmdHandlerDelegates.TryGetValue(cmdHash, out invoker) &&
- invoker != null &&
- invoker.invokeType == invokeType)
- {
- return true;
- }
-
- // debug message if not found, or null, or mismatched type
- // (no need to throw an error, an attacker might just be trying to
- // call an cmd with an rpc's hash)
- if (LogFilter.Debug) Debug.Log("GetInvokerForHash hash:" + cmdHash + " not found");
- return false;
- }
- // InvokeCmd/Rpc/SyncEventDelegate can all use the same function here
- internal bool InvokeHandlerDelegate(int cmdHash, MirrorInvokeType invokeType, NetworkReader reader)
- {
- if (GetInvokerForHash(cmdHash, invokeType, out Invoker invoker) &&
- invoker.invokeClass.IsInstanceOfType(this))
- {
- invoker.invokeFunction(this, reader);
- return true;
- }
- return false;
- }
-
- ///
- /// Gets the handler function for a given hash
- /// Can be used by profilers and debuggers
- ///
- /// rpc function hash
- /// The function delegate that will handle the command
- public static CmdDelegate GetRpcHandler(int cmdHash)
- {
- if (cmdHandlerDelegates.TryGetValue(cmdHash, out Invoker invoker))
- {
- return invoker.invokeFunction;
- }
- return null;
+ return newNetId == netIdField;
}
- #endregion
-
- #region Helpers
// helper function for [SyncVar] GameObjects.
[EditorBrowsable(EditorBrowsableState.Never)]
protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gameObjectField, ulong dirtyBit, ref uint netIdField)
@@ -474,19 +385,16 @@ protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gam
newNetId = identity.netId;
if (newNetId == 0)
{
- Debug.LogWarning("SetSyncVarGameObject GameObject " + newGameObject + " has a zero netId. Maybe it is not spawned yet?");
+ logger.LogWarning("SetSyncVarGameObject GameObject " + newGameObject + " has a zero netId. Maybe it is not spawned yet?");
}
}
}
- // netId changed?
- if (newNetId != netIdField)
- {
- if (LogFilter.Debug) Debug.Log("SetSyncVar GameObject " + GetType().Name + " bit [" + dirtyBit + "] netfieldId:" + netIdField + "->" + newNetId);
- SetDirtyBit(dirtyBit);
- gameObjectField = newGameObject; // assign new one on the server, and in case we ever need it on client too
- netIdField = newNetId;
- }
+ if (logger.LogEnabled()) logger.Log("SetSyncVar GameObject " + GetType().Name + " bit [" + dirtyBit + "] netfieldId:" + netIdField + "->" + newNetId);
+ SetDirtyBit(dirtyBit);
+ // assign new one on the server, and in case we ever need it on client too
+ gameObjectField = newGameObject;
+ netIdField = newNetId;
}
// helper function for [SyncVar] GameObjects.
@@ -503,10 +411,30 @@ protected GameObject GetSyncVarGameObject(uint netId, ref GameObject gameObjectF
// client always looks up based on netId because objects might get in and out of range
// over and over again, which shouldn't null them forever
if (NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity identity) && identity != null)
- return identity.gameObject;
+ return gameObjectField = identity.gameObject;
return null;
}
+ // helper function for [SyncVar] NetworkIdentities.
+ // IMPORTANT: keep as 'protected', not 'internal', otherwise Weaver
+ // can't resolve it
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected bool SyncVarNetworkIdentityEqual(NetworkIdentity newIdentity, uint netIdField)
+ {
+ uint newNetId = 0;
+ if (newIdentity != null)
+ {
+ newNetId = newIdentity.netId;
+ if (newNetId == 0)
+ {
+ logger.LogWarning("SetSyncVarNetworkIdentity NetworkIdentity " + newIdentity + " has a zero netId. Maybe it is not spawned yet?");
+ }
+ }
+
+ // netId changed?
+ return newNetId == netIdField;
+ }
+
// helper function for [SyncVar] NetworkIdentities.
[EditorBrowsable(EditorBrowsableState.Never)]
protected void SetSyncVarNetworkIdentity(NetworkIdentity newIdentity, ref NetworkIdentity identityField, ulong dirtyBit, ref uint netIdField)
@@ -520,18 +448,15 @@ protected void SetSyncVarNetworkIdentity(NetworkIdentity newIdentity, ref Networ
newNetId = newIdentity.netId;
if (newNetId == 0)
{
- Debug.LogWarning("SetSyncVarNetworkIdentity NetworkIdentity " + newIdentity + " has a zero netId. Maybe it is not spawned yet?");
+ logger.LogWarning("SetSyncVarNetworkIdentity NetworkIdentity " + newIdentity + " has a zero netId. Maybe it is not spawned yet?");
}
}
- // netId changed?
- if (newNetId != netIdField)
- {
- if (LogFilter.Debug) Debug.Log("SetSyncVarNetworkIdentity NetworkIdentity " + GetType().Name + " bit [" + dirtyBit + "] netIdField:" + netIdField + "->" + newNetId);
- SetDirtyBit(dirtyBit);
- netIdField = newNetId;
- identityField = newIdentity; // assign new one on the server, and in case we ever need it on client too
- }
+ if (logger.LogEnabled()) logger.Log("SetSyncVarNetworkIdentity NetworkIdentity " + GetType().Name + " bit [" + dirtyBit + "] netIdField:" + netIdField + "->" + newNetId);
+ SetDirtyBit(dirtyBit);
+ netIdField = newNetId;
+ // assign new one on the server, and in case we ever need it on client too
+ identityField = newIdentity;
}
// helper function for [SyncVar] NetworkIdentities.
@@ -547,20 +472,23 @@ protected NetworkIdentity GetSyncVarNetworkIdentity(uint netId, ref NetworkIdent
// client always looks up based on netId because objects might get in and out of range
// over and over again, which shouldn't null them forever
- NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity identity);
- return identity;
+ NetworkIdentity.spawned.TryGetValue(netId, out identityField);
+ return identityField;
}
[EditorBrowsable(EditorBrowsableState.Never)]
- protected void SetSyncVar(T value, ref T fieldValue, ulong dirtyBit)
+ protected bool SyncVarEqual(T value, ref T fieldValue)
{
// newly initialized or changed value?
- if (!EqualityComparer.Default.Equals(value, fieldValue))
- {
- if (LogFilter.Debug) Debug.Log("SetSyncVar " + GetType().Name + " bit [" + dirtyBit + "] " + fieldValue + "->" + value);
- SetDirtyBit(dirtyBit);
- fieldValue = value;
- }
+ return EqualityComparer.Default.Equals(value, fieldValue);
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected void SetSyncVar(T value, ref T fieldValue, ulong dirtyBit)
+ {
+ if (logger.LogEnabled()) logger.Log("SetSyncVar " + GetType().Name + " bit [" + dirtyBit + "] " + fieldValue + "->" + value);
+ SetDirtyBit(dirtyBit);
+ fieldValue = value;
}
#endregion
@@ -630,13 +558,24 @@ internal bool IsDirty()
/// True if data was written.
public virtual bool OnSerialize(NetworkWriter writer, bool initialState)
{
+ bool objectWritten = false;
+ // if initialState: write all SyncVars.
+ // otherwise write dirtyBits+dirty SyncVars
if (initialState)
{
- return SerializeObjectsAll(writer);
+ objectWritten = SerializeObjectsAll(writer);
}
- return SerializeObjectsDelta(writer);
+ else
+ {
+ objectWritten = SerializeObjectsDelta(writer);
+ }
+
+ bool syncVarWritten = SerializeSyncVars(writer, initialState);
+
+ return objectWritten || syncVarWritten;
}
+
///
/// Virtual function to override to receive custom serialization data. The corresponding function to send serialization data is OnSerialize().
///
@@ -652,9 +591,37 @@ public virtual void OnDeserialize(NetworkReader reader, bool initialState)
{
DeSerializeObjectsDelta(reader);
}
+
+ DeserializeSyncVars(reader, initialState);
}
- ulong DirtyObjectBits()
+ // Don't rename. Weaver uses this exact function name.
+ public virtual bool SerializeSyncVars(NetworkWriter writer, bool initialState)
+ {
+ return false;
+
+ // SyncVar are writen here in subclass
+
+ // if initialState
+ // write all SyncVars
+ // else
+ // write syncVarDirtyBits
+ // write dirty SyncVars
+ }
+
+ // Don't rename. Weaver uses this exact function name.
+ public virtual void DeserializeSyncVars(NetworkReader reader, bool initialState)
+ {
+ // SyncVars are read here in subclass
+
+ // if initialState
+ // read all SyncVars
+ // else
+ // read syncVarDirtyBits
+ // read dirty SyncVars
+ }
+
+ internal ulong DirtyObjectBits()
{
ulong dirtyObjects = 0;
for (int i = 0; i < syncObjects.Count; i++)
@@ -698,7 +665,7 @@ public bool SerializeObjectsDelta(NetworkWriter writer)
return dirty;
}
- void DeSerializeObjectsAll(NetworkReader reader)
+ internal void DeSerializeObjectsAll(NetworkReader reader)
{
for (int i = 0; i < syncObjects.Count; i++)
{
@@ -707,7 +674,7 @@ void DeSerializeObjectsAll(NetworkReader reader)
}
}
- void DeSerializeObjectsDelta(NetworkReader reader)
+ internal void DeSerializeObjectsDelta(NetworkReader reader)
{
ulong dirty = reader.ReadPackedUInt64();
for (int i = 0; i < syncObjects.Count; i++)
@@ -720,73 +687,69 @@ void DeSerializeObjectsDelta(NetworkReader reader)
}
}
+ internal void ResetSyncObjects()
+ {
+ foreach (SyncObject syncObject in syncObjects)
+ {
+ syncObject.Reset();
+ }
+ }
+
+ // Deprecated 04/20/2020
+ ///
+ /// Obsolete: Use OnStopClient() instead
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Override OnStopClient() instead")]
+ public virtual void OnNetworkDestroy() { }
+
///
/// This is invoked on clients when the server has caused this object to be destroyed.
/// This can be used as a hook to invoke effects or do client specific cleanup.
///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public virtual void OnNetworkDestroy() {}
+ public virtual void OnStopClient()
+ {
+#pragma warning disable CS0618 // Type or member is obsolete
+ // backwards compatibility
+ OnNetworkDestroy();
+#pragma warning restore CS0618 // Type or member is obsolete
+ }
///
/// This is invoked for NetworkBehaviour objects when they become active on the server.
/// This could be triggered by NetworkServer.Listen() for objects in the scene, or by NetworkServer.Spawn() for objects that are dynamically created.
/// This will be called for objects on a "host" as well as for object on a dedicated server.
///
- public virtual void OnStartServer() {}
+ public virtual void OnStartServer() { }
+
+ ///
+ /// Invoked on the server when the object is unspawned
+ /// Useful for saving object data in persistant storage
+ ///
+ public virtual void OnStopServer() { }
///
/// Called on every NetworkBehaviour when it is activated on a client.
/// Objects on the host have this function called, as there is a local client on the host. The values of SyncVars on object are guaranteed to be initialized correctly with the latest state from the server when this function is called on the client.
///
- public virtual void OnStartClient() {}
+ public virtual void OnStartClient() { }
///
/// Called when the local player object has been set up.
/// This happens after OnStartClient(), as it is triggered by an ownership message from the server. This is an appropriate place to activate components or functionality that should only be active for the local player, such as cameras and input.
///
- public virtual void OnStartLocalPlayer() {}
+ public virtual void OnStartLocalPlayer() { }
///
- /// This is invoked on behaviours that have authority, based on context and 'NetworkIdentity.localPlayerAuthority.'
- /// This is called after OnStartServer and OnStartClient.
- /// When is called on the server, this will be called on the client that owns the object. When an object is spawned with NetworkServer.SpawnWithClientAuthority, this will be called on the client that owns the object.
+ /// This is invoked on behaviours that have authority, based on context and NetworkIdentity.hasAuthority.
+ /// This is called after OnStartServer and before OnStartClient.
+ /// When AssignClientAuthority is called on the server, this will be called on the client that owns the object. When an object is spawned with NetworkServer.Spawn with a NetworkConnection parameter included, this will be called on the client that owns the object.
///
- public virtual void OnStartAuthority() {}
+ public virtual void OnStartAuthority() { }
///
/// This is invoked on behaviours when authority is removed.
/// When NetworkIdentity.RemoveClientAuthority is called on the server, this will be called on the client that owns the object.
///
- public virtual void OnStopAuthority() {}
-
- ///
- /// Callback used by the visibility system to (re)construct the set of observers that can see this object.
- /// Implementations of this callback should add network connections of players that can see this object to the observers set.
- ///
- /// The new set of observers for this object.
- /// True if the set of observers is being built for the first time.
- /// true when overwriting so that Mirror knows that we wanted to rebuild observers ourselves. otherwise it uses built in rebuild.
- public virtual bool OnRebuildObservers(HashSet observers, bool initialize)
- {
- return false;
- }
-
- ///
- /// Callback used by the visibility system for objects on a host.
- /// Objects on a host (with a local client) cannot be disabled or destroyed when they are not visibile to the local client. So this function is called to allow custom code to hide these objects. A typical implementation will disable renderer components on the object. This is only called on local clients on a host.
- ///
- /// New visibility state.
- public virtual void OnSetLocalVisibility(bool vis) {}
-
- ///
- /// Callback used by the visibility system to determine if an observer (player) can see this object.
- /// If this function returns true, the network connection will be added as an observer.
- ///
- /// Network connection of a player.
- /// True if the player can see this object.
- public virtual bool OnCheckObserver(NetworkConnection conn)
- {
- return true;
- }
+ public virtual void OnStopAuthority() { }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkClient.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkClient.cs
index 7c8c1c9..7ffd904 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkClient.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkClient.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using UnityEngine;
namespace Mirror
@@ -13,33 +12,20 @@ public enum ConnectState
Disconnected
}
- // TODO make fully static after removing obsoleted singleton!
///
/// This is a network client class used by the networking system. It contains a NetworkConnection that is used to connect to a network server.
/// The NetworkClient handle connection state, messages handlers, and connection configuration. There can be many NetworkClient instances in a process at a time, but only one that is connected to a game server (NetworkServer) that uses spawned objects.
/// NetworkClient has an internal update function where it handles events from the transport layer. This includes asynchronous connect events, disconnect events and incoming data from a server.
/// The NetworkManager has a NetworkClient instance that it uses for games that it starts, but the NetworkClient may be used by itself.
///
- public class NetworkClient
+ public static class NetworkClient
{
- ///
- /// Obsolete: Use directly.
- /// Singleton isn't needed anymore, all functions are static now. For example: NetworkClient.Send(message) instead of NetworkClient.singleton.Send(message).
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use NetworkClient directly. Singleton isn't needed anymore, all functions are static now. For example: NetworkClient.Send(message) instead of NetworkClient.singleton.Send(message).")]
- public static NetworkClient singleton = new NetworkClient();
-
- ///
- /// A list of all the active network clients in the current process.
- /// This is NOT a list of all clients that are connected to the remote server, it is client instances on the local game.
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use NetworkClient directly instead. There is always exactly one client.")]
- public static List allClients => new List { singleton };
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkClient));
///
/// The registered network message handlers.
///
- public static readonly Dictionary handlers = new Dictionary();
+ static readonly Dictionary handlers = new Dictionary();
///
/// The NetworkConnection object this client is using.
@@ -70,18 +56,13 @@ public class NetworkClient
///
public static bool isLocalClient => connection is ULocalConnectionToServer;
- // local client in host mode might call Cmds/Rpcs during Update, but we
- // want to apply them in LateUpdate like all other Transport messages
- // to avoid race conditions. keep packets in Queue until LateUpdate.
- internal static Queue localClientPacketQueue = new Queue();
-
///
/// Connect client to a NetworkServer instance.
///
///
public static void Connect(string address)
{
- if (LogFilter.Debug) Debug.Log("Client Connect: " + address);
+ if (logger.LogEnabled()) logger.Log("Client Connect: " + address);
RegisterSystemHandlers(false);
Transport.activeTransport.enabled = true;
@@ -91,48 +72,75 @@ public static void Connect(string address)
Transport.activeTransport.ClientConnect(address);
// setup all the handlers
- connection = new NetworkConnection(address, 0);
+ connection = new NetworkConnectionToServer();
connection.SetHandlers(handlers);
}
///
- /// connect host mode
+ /// Connect client to a NetworkServer instance.
///
- internal static void ConnectLocalServer()
+ /// Address of the server to connect to
+ public static void Connect(Uri uri)
{
- if (LogFilter.Debug) Debug.Log("Client Connect Local Server");
+ if (logger.LogEnabled()) logger.Log("Client Connect: " + uri);
+
+ RegisterSystemHandlers(false);
+ Transport.activeTransport.enabled = true;
+ InitializeTransportHandlers();
+
+ connectState = ConnectState.Connecting;
+ Transport.activeTransport.ClientConnect(uri);
+
+ // setup all the handlers
+ connection = new NetworkConnectionToServer();
+ connection.SetHandlers(handlers);
+ }
+
+ public static void ConnectHost()
+ {
+ logger.Log("Client Connect Host to Server");
RegisterSystemHandlers(true);
connectState = ConnectState.Connected;
- // create local connection to server
- connection = new ULocalConnectionToServer();
+ // create local connection objects and connect them
+ ULocalConnectionToServer connectionToServer = new ULocalConnectionToServer();
+ ULocalConnectionToClient connectionToClient = new ULocalConnectionToClient();
+ connectionToServer.connectionToClient = connectionToClient;
+ connectionToClient.connectionToServer = connectionToServer;
+
+ connection = connectionToServer;
connection.SetHandlers(handlers);
// create server connection to local client
- ULocalConnectionToClient connectionToClient = new ULocalConnectionToClient();
NetworkServer.SetLocalConnection(connectionToClient);
- connectionToClient.Send(new ConnectMessage());
}
///
- /// Called by the server to set the LocalClient's LocalPlayer object during NetworkServer.AddPlayer()
+ /// connect host mode
+ ///
+ public static void ConnectLocalServer()
+ {
+ NetworkServer.OnConnected(NetworkServer.localConnection);
+ NetworkServer.localConnection.Send(new ConnectMessage());
+ }
+
+ ///
+ /// disconnect host mode. this is needed to call DisconnectMessage for
+ /// the host client too.
///
- ///
- internal static void AddLocalPlayer(NetworkIdentity localPlayer)
+ public static void DisconnectLocalServer()
{
- if (LogFilter.Debug) Debug.Log("Local client AddLocalPlayer " + localPlayer.gameObject.name + " conn=" + connection.connectionId);
- connection.isReady = true;
- connection.identity = localPlayer;
- if (localPlayer != null)
+ // only if host connection is running
+ if (NetworkServer.localConnection != null)
{
- localPlayer.isClient = true;
- NetworkIdentity.spawned[localPlayer.netId] = localPlayer;
- localPlayer.connectionToServer = connection;
+ // TODO ConnectLocalServer manually sends a ConnectMessage to the
+ // local connection. should we send a DisconnectMessage here too?
+ // (if we do then we get an Unknown Message ID log)
+ //NetworkServer.localConnection.Send(new DisconnectMessage());
+ NetworkServer.OnDisconnected(NetworkServer.localConnection.connectionId);
}
- // there is no SystemOwnerMessage for local client. add to ClientScene here instead
- ClientScene.InternalAddPlayer(localPlayer);
}
static void InitializeTransportHandlers()
@@ -145,7 +153,7 @@ static void InitializeTransportHandlers()
static void OnError(Exception exception)
{
- Debug.LogException(exception);
+ logger.LogException(exception);
}
static void OnDisconnected()
@@ -163,7 +171,7 @@ internal static void OnDataReceived(ArraySegment data, int channelId)
{
connection.TransportReceive(data, channelId);
}
- else Debug.LogError("Skipped Data message handling because connection is null.");
+ else logger.LogError("Skipped Data message handling because connection is null.");
}
static void OnConnected()
@@ -179,7 +187,7 @@ static void OnConnected()
NetworkTime.UpdateClient();
connection.InvokeHandler(new ConnectMessage(), -1);
}
- else Debug.LogError("Skipped Connect message handling because connection is null.");
+ else logger.LogError("Skipped Connect message handling because connection is null.");
}
///
@@ -221,25 +229,6 @@ static void RemoveTransportHandlers()
Transport.activeTransport.OnClientError.RemoveListener(OnError);
}
- ///
- /// Obsolete: Use instead with no message id instead
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use SendMessage instead with no message id instead")]
- public static bool Send(short msgType, MessageBase msg)
- {
- if (connection != null)
- {
- if (connectState != ConnectState.Connected)
- {
- Debug.LogError("NetworkClient Send when not connected to a server");
- return false;
- }
- return connection.Send(msgType, msg);
- }
- Debug.LogError("NetworkClient Send with no connection");
- return false;
- }
-
///
/// This sends a network message with a message Id to the server. This message is sent on channel zero, which by default is the reliable channel.
/// The message must be an instance of a class derived from MessageBase.
@@ -255,30 +244,23 @@ public static bool Send(T message, int channelId = Channels.DefaultReliable)
{
if (connectState != ConnectState.Connected)
{
- Debug.LogError("NetworkClient Send when not connected to a server");
+ logger.LogError("NetworkClient Send when not connected to a server");
return false;
}
return connection.Send(message, channelId);
}
- Debug.LogError("NetworkClient Send with no connection");
+ logger.LogError("NetworkClient Send with no connection");
return false;
}
- internal static void Update()
+ public static void Update()
{
- // local or remote connection?
- if (isLocalClient)
+ // local connection?
+ if (connection is ULocalConnectionToServer localConnection)
{
- // process internal messages so they are applied at the correct time
- while (localClientPacketQueue.Count > 0)
- {
- NetworkWriter writer = localClientPacketQueue.Dequeue();
- // TODO avoid serializing and deserializng the message
- // just pass it as is
- OnDataReceived(writer.ToArraySegment(), Channels.DefaultReliable);
- NetworkWriterPool.Recycle(writer);
- }
+ localConnection.Update();
}
+ // remote connection?
else
{
// only update things while connected
@@ -289,75 +271,21 @@ internal static void Update()
}
}
- /* TODO use or remove
- void GenerateConnectError(byte error)
- {
- Debug.LogError("Mirror Client Error Connect Error: " + error);
- GenerateError(error);
- }
-
- void GenerateDataError(byte error)
- {
- NetworkError dataError = (NetworkError)error;
- Debug.LogError("Mirror Client Data Error: " + dataError);
- GenerateError(error);
- }
-
- void GenerateDisconnectError(byte error)
- {
- NetworkError disconnectError = (NetworkError)error;
- Debug.LogError("Mirror Client Disconnect Error: " + disconnectError);
- GenerateError(error);
- }
-
- void GenerateError(byte error)
+ internal static void RegisterSystemHandlers(bool hostMode)
{
- int msgId = MessageBase.GetId();
- if (handlers.TryGetValue(msgId, out NetworkMessageDelegate msgDelegate))
- {
- ErrorMessage msg = new ErrorMessage
- {
- value = error
- };
-
- // write the message to a local buffer
- NetworkWriter writer = new NetworkWriter();
- msg.Serialize(writer);
-
- NetworkMessage netMsg = new NetworkMessage
- {
- msgType = msgId,
- reader = new NetworkReader(writer.ToArray()),
- conn = connection
- };
- msgDelegate(netMsg);
- }
- }
- */
-
- ///
- /// Obsolete: Use instead
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use NetworkTime.rtt instead")]
- public static float GetRTT()
- {
- return (float)NetworkTime.rtt;
- }
-
- internal static void RegisterSystemHandlers(bool localClient)
- {
- // local client / regular client react to some messages differently.
+ // host mode client / regular client react to some messages differently.
// but we still need to add handlers for all of them to avoid
// 'message id not found' errors.
- if (localClient)
+ if (hostMode)
{
- RegisterHandler(ClientScene.OnLocalClientObjectDestroy);
- RegisterHandler(ClientScene.OnLocalClientObjectHide);
+ RegisterHandler(ClientScene.OnHostClientObjectDestroy);
+ RegisterHandler(ClientScene.OnHostClientObjectHide);
RegisterHandler((conn, msg) => { }, false);
- RegisterHandler(ClientScene.OnLocalClientSpawnPrefab);
- RegisterHandler(ClientScene.OnLocalClientSpawnSceneObject);
- RegisterHandler((conn, msg) => { }); // host mode doesn't need spawning
- RegisterHandler((conn, msg) => { }); // host mode doesn't need spawning
+ RegisterHandler(ClientScene.OnHostClientSpawn);
+ // host mode doesn't need spawning
+ RegisterHandler((conn, msg) => { });
+ // host mode doesn't need spawning
+ RegisterHandler((conn, msg) => { });
RegisterHandler((conn, msg) => { });
}
else
@@ -365,83 +293,78 @@ internal static void RegisterSystemHandlers(bool localClient)
RegisterHandler(ClientScene.OnObjectDestroy);
RegisterHandler(ClientScene.OnObjectHide);
RegisterHandler(NetworkTime.OnClientPong, false);
- RegisterHandler(ClientScene.OnSpawnPrefab);
- RegisterHandler(ClientScene.OnSpawnSceneObject);
+ RegisterHandler(ClientScene.OnSpawn);
RegisterHandler(ClientScene.OnObjectSpawnStarted);
RegisterHandler(ClientScene.OnObjectSpawnFinished);
RegisterHandler(ClientScene.OnUpdateVarsMessage);
}
- RegisterHandler(ClientScene.OnClientAuthority);
RegisterHandler(ClientScene.OnRPCMessage);
RegisterHandler(ClientScene.OnSyncEventMessage);
}
///
- /// Obsolete: Use instead
+ /// Register a handler for a particular message type.
+ /// There are several system message types which you can add handlers for. You can also add your own message types.
///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use RegisterHandler instead")]
- public static void RegisterHandler(int msgType, NetworkMessageDelegate handler)
+ /// Message type
+ /// Function handler which will be invoked when this message type is received.
+ /// True if the message requires an authenticated connection
+ public static void RegisterHandler(Action handler, bool requireAuthentication = true) where T : IMessageBase, new()
{
+ int msgType = MessagePacker.GetId();
if (handlers.ContainsKey(msgType))
{
- if (LogFilter.Debug) Debug.Log("NetworkClient.RegisterHandler replacing " + handler + " - " + msgType);
+ logger.LogWarning($"NetworkClient.RegisterHandler replacing handler for {typeof(T).FullName}, id={msgType}. If replacement is intentional, use ReplaceHandler instead to avoid this warning.");
}
- handlers[msgType] = handler;
- }
-
- ///
- /// Obsolete: Use instead
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use RegisterHandler instead")]
- public static void RegisterHandler(MsgType msgType, NetworkMessageDelegate handler)
- {
- RegisterHandler((int)msgType, handler);
+ handlers[msgType] = MessagePacker.MessageHandler(handler, requireAuthentication);
}
///
/// Register a handler for a particular message type.
/// There are several system message types which you can add handlers for. You can also add your own message types.
///
- /// The message type to unregister.
- ///
- /// true if the message requires an authenticated connection
- public static void RegisterHandler(Action handler, bool requireAuthentication = true) where T : IMessageBase, new()
+ /// Message type
+ /// Function handler which will be invoked when this message type is received.
+ /// True if the message requires an authenticated connection
+ public static void RegisterHandler(Action handler, bool requireAuthentication = true) where T : IMessageBase, new()
{
- int msgType = MessagePacker.GetId();
- if (handlers.ContainsKey(msgType))
- {
- if (LogFilter.Debug) Debug.Log("NetworkClient.RegisterHandler replacing " + handler + " - " + msgType);
- }
- handlers[msgType] = MessagePacker.MessageHandler(handler, requireAuthentication);
+ RegisterHandler((NetworkConnection _, T value) => { handler(value); }, requireAuthentication);
}
///
- /// Obsolete: Use instead
+ /// Replaces a handler for a particular message type.
+ /// See also RegisterHandler(T)(Action(NetworkConnection, T), bool)
///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use UnregisterHandler instead")]
- public static void UnregisterHandler(int msgType)
+ /// Message type
+ /// Function handler which will be invoked when this message type is received.
+ /// True if the message requires an authenticated connection
+ public static void ReplaceHandler(Action handler, bool requireAuthentication = true) where T : IMessageBase, new()
{
- handlers.Remove(msgType);
+ int msgType = MessagePacker.GetId();
+ handlers[msgType] = MessagePacker.MessageHandler(handler, requireAuthentication);
}
///
- /// Obsolete: Use instead
+ /// Replaces a handler for a particular message type.
+ /// See also RegisterHandler(T)(Action(NetworkConnection, T), bool)
///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use UnregisterHandler instead")]
- public static void UnregisterHandler(MsgType msgType)
+ /// Message type
+ /// Function handler which will be invoked when this message type is received.
+ /// True if the message requires an authenticated connection
+ public static void ReplaceHandler(Action handler, bool requireAuthentication = true) where T : IMessageBase, new()
{
- UnregisterHandler((int)msgType);
+ ReplaceHandler((NetworkConnection _, T value) => { handler(value); }, requireAuthentication);
}
///
/// Unregisters a network message handler.
///
/// The message type to unregister.
- public static void UnregisterHandler() where T : IMessageBase
+ public static bool UnregisterHandler() where T : IMessageBase
{
// use int to minimize collisions
int msgType = MessagePacker.GetId();
- handlers.Remove(msgType);
+ return handlers.Remove(msgType);
}
///
@@ -450,19 +373,15 @@ public static void UnregisterHandler() where T : IMessageBase
///
public static void Shutdown()
{
- if (LogFilter.Debug) Debug.Log("Shutting down client.");
+ logger.Log("Shutting down client.");
ClientScene.Shutdown();
connectState = ConnectState.None;
handlers.Clear();
- }
-
- ///
- /// Obsolete: Call instead. There is only one client.
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Call NetworkClient.Shutdown() instead. There is only one client.")]
- public static void ShutdownAll()
- {
- Shutdown();
+ // disconnect the client connection.
+ // we do NOT call Transport.Shutdown, because someone only called
+ // NetworkClient.Shutdown. we can't assume that the server is
+ // supposed to be shut down too!
+ Transport.activeTransport.ClientDisconnect();
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnection.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnection.cs
index 5ef0689..df8d385 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnection.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnection.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using UnityEngine;
namespace Mirror
@@ -13,12 +12,15 @@ namespace Mirror
/// A NetworkClient has one NetworkConnection. A NetworkServerSimple manages multiple NetworkConnections. The NetworkServer has multiple "remote" connections and a "local" connection for the local client.
/// The NetworkConnection class provides message sending and handling facilities. For sending data over a network, there are methods to send message objects, byte arrays, and NetworkWriter objects. To handle data arriving from the network, handler functions can be registered for message Ids, byte arrays can be processed by HandleBytes(), and NetworkReader object can be processed by HandleReader().
/// NetworkConnection objects also act as observers for networked objects. When a connection is an observer of a networked object with a NetworkIdentity, then the object will be visible to corresponding client for the connection, and incremental state changes will be sent to the client.
- /// NetworkConnection objects can "own" networked game objects. Owned objects will be destroyed on the server by default when the connection is destroyed. A connection owns the player objects created by its client, and other objects with client-authority assigned to the corresponding client.
/// There are many virtual functions on NetworkConnection that allow its behaviour to be customized. NetworkClient and NetworkServer can both be made to instantiate custom classes derived from NetworkConnection by setting their networkConnectionClass member variable.
///
- public class NetworkConnection : IDisposable
+ public abstract class NetworkConnection : IDisposable
{
- public readonly HashSet visList = new HashSet();
+ public const int LocalConnectionId = 0;
+ static readonly ILogger logger = LogFactory.GetLogger();
+
+ // internal so it can be tested
+ internal readonly HashSet visList = new HashSet();
Dictionary messageHandlers;
@@ -30,7 +32,7 @@ public class NetworkConnection : IDisposable
/// Transport layers connections begin at one. So on a client with a single connection to a server, the connectionId of that connection will be one. In NetworkServer, the connectionId of the local connection is zero.
/// Clients do not know their connectionId on the server, and do not know the connectionId of other clients on the server.
///
- public int connectionId = -1;
+ public readonly int connectionId;
///
/// Flag that indicates the client has been authenticated.
@@ -52,8 +54,9 @@ public class NetworkConnection : IDisposable
///
/// The IP address / URL / FQDN associated with the connection.
+ /// Can be useful for a game master to do IP Bans etc.
///
- public string address;
+ public abstract string address { get; }
///
/// The last time that a message was received on this connection.
@@ -61,22 +64,6 @@ public class NetworkConnection : IDisposable
///
public float lastMessageTime;
- ///
- /// Obsolete: use instead
- ///
- [Obsolete("Use NetworkConnection.identity instead")]
- public NetworkIdentity playerController
- {
- get
- {
- return identity;
- }
- internal set
- {
- identity = value;
- }
- }
-
///
/// The NetworkIdentity for this connection.
///
@@ -87,7 +74,9 @@ internal set
/// This includes the player object for the connection - if it has localPlayerAutority set, and any objects spawned with local authority or set with AssignLocalAuthority.
/// This list can be used to validate messages from clients, to ensure that clients are only trying to control objects that they own.
///
- public readonly HashSet clientOwnedObjects = new HashSet();
+ // IMPORTANT: this needs to be , not . fixes a bug where DestroyOwnedObjects wouldn't find
+ // the netId anymore: https://github.com/vis2k/Mirror/issues/1380 . Works fine with NetworkIdentity pointers though.
+ public readonly HashSet clientOwnedObjects = new HashSet();
///
/// Setting this to true will log the contents of network message to the console.
@@ -97,40 +86,25 @@ internal set
/// ConnectionSend con:1 bytes:11 msgId:5 FB59D743FD120000000000 ConnectionRecv con:1 bytes:27 msgId:8 14F21000000000016800AC3FE090C240437846403CDDC0BD3B0000
/// Note that these are application-level network messages, not protocol-level packets. There will typically be multiple network messages combined in a single protocol packet.
///
+ [Obsolete("Set logger to Log level instead")]
public bool logNetworkMessages;
- // this is always true for regular connections, false for local
- // connections because it's set in the constructor and never reset.
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("isConnected will be removed because it's pointless. A NetworkConnection is always connected.")]
- public bool isConnected { get; protected set; }
-
- // this is always 0 for regular connections, -1 for local
- // connections because it's set in the constructor and never reset.
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("hostId will be removed because it's not needed ever since we removed LLAPI as default. It's always 0 for regular connections and -1 for local connections. Use connection.GetType() == typeof(NetworkConnection) to check if it's a regular or local connection.")]
- public int hostId = -1;
-
///
- /// Creates a new NetworkConnection with the specified address
+ /// Creates a new NetworkConnection
///
- ///
- public NetworkConnection(string networkAddress)
+ internal NetworkConnection()
{
- address = networkAddress;
+ // set lastTime to current time when creating connection to make sure it isn't instantly kicked for inactivity
+ lastMessageTime = Time.time;
}
///
- /// Creates a new NetworkConnection with the specified address and connectionId
+ /// Creates a new NetworkConnection with the specified connectionId
///
- ///
///
- public NetworkConnection(string networkAddress, int networkConnectionId)
+ internal NetworkConnection(int networkConnectionId) : this()
{
- address = networkAddress;
connectionId = networkConnectionId;
-#pragma warning disable 618
- isConnected = true;
- hostId = 0;
-#pragma warning restore 618
}
~NetworkConnection()
@@ -152,83 +126,19 @@ public void Dispose()
protected virtual void Dispose(bool disposing)
{
- foreach (uint netId in clientOwnedObjects)
- {
- if (NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity identity))
- {
- identity.clientAuthorityOwner = null;
- }
- }
clientOwnedObjects.Clear();
}
///
/// Disconnects this connection.
///
- public void Disconnect()
- {
- // don't clear address so we can still access it in NetworkManager.OnServerDisconnect
- // => it's reset in Initialize anyway and there is no address empty check anywhere either
- //address = "";
-
- // set not ready and handle clientscene disconnect in any case
- // (might be client or host mode here)
- isReady = false;
- ClientScene.HandleClientDisconnect(this);
-
- // server? then disconnect that client (not for host local player though)
- if (Transport.activeTransport.ServerActive() && connectionId != 0)
- {
- Transport.activeTransport.ServerDisconnect(connectionId);
- }
- // not server and not host mode? then disconnect client
- else
- {
- Transport.activeTransport.ClientDisconnect();
- }
-
- RemoveObservers();
- }
+ public abstract void Disconnect();
internal void SetHandlers(Dictionary handlers)
{
messageHandlers = handlers;
}
- ///
- /// Obsolete: Use NetworkClient/NetworkServer.RegisterHandler{T} instead
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use NetworkClient/NetworkServer.RegisterHandler instead")]
- public void RegisterHandler(short msgType, NetworkMessageDelegate handler)
- {
- if (messageHandlers.ContainsKey(msgType))
- {
- if (LogFilter.Debug) Debug.Log("NetworkConnection.RegisterHandler replacing " + msgType);
- }
- messageHandlers[msgType] = handler;
- }
-
- ///
- /// Obsolete: Use and instead
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use NetworkClient/NetworkServer.UnregisterHandler instead")]
- public void UnregisterHandler(short msgType)
- {
- messageHandlers.Remove(msgType);
- }
-
- ///
- /// Obsolete: use instead
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("use Send instead")]
- public virtual bool Send(int msgType, MessageBase msg, int channelId = Channels.DefaultReliable)
- {
- // pack message and send
- byte[] message = MessagePacker.PackMessage(msgType, msg);
- return Send(new ArraySegment(message), channelId);
- }
-
-
///
/// This sends a network message with a message ID on the connection. This message is sent on channel zero, which by default is the reliable channel.
///
@@ -236,17 +146,15 @@ public virtual bool Send(int msgType, MessageBase msg, int channelId = Channels.
/// The message to send.
/// The transport layer channel to send on.
///
- public virtual bool Send(T msg, int channelId = Channels.DefaultReliable) where T : IMessageBase
+ public bool Send(T msg, int channelId = Channels.DefaultReliable) where T : IMessageBase
{
- NetworkWriter writer = NetworkWriterPool.GetWriter();
-
- // pack message and send allocation free
- MessagePacker.Pack(msg, writer);
- NetworkDiagnostics.OnSend(msg, channelId, writer.Position, 1);
- bool result = Send(writer.ToArraySegment(), channelId);
-
- NetworkWriterPool.Recycle(writer);
- return result;
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
+ {
+ // pack message and send allocation free
+ MessagePacker.Pack(msg, writer);
+ NetworkDiagnostics.OnSend(msg, channelId, writer.Position, 1);
+ return Send(writer.ToArraySegment(), channelId);
+ }
}
// validate packet size before sending. show errors if too big/small.
@@ -254,18 +162,18 @@ public virtual bool Send(T msg, int channelId = Channels.DefaultReliable) whe
// would check max size and show errors internally. best to do it
// in one place in hlapi.
// => it's important to log errors, so the user knows what went wrong.
- static bool ValidatePacketSize(ArraySegment segment, int channelId)
+ protected internal static bool ValidatePacketSize(ArraySegment segment, int channelId)
{
if (segment.Count > Transport.activeTransport.GetMaxPacketSize(channelId))
{
- Debug.LogError("NetworkConnection.ValidatePacketSize: cannot send packet larger than " + Transport.activeTransport.GetMaxPacketSize(channelId) + " bytes");
+ logger.LogError("NetworkConnection.ValidatePacketSize: cannot send packet larger than " + Transport.activeTransport.GetMaxPacketSize(channelId) + " bytes");
return false;
}
if (segment.Count == 0)
{
// zero length packets getting into the packet queues are bad.
- Debug.LogError("NetworkConnection.ValidatePacketSize: cannot send zero bytes");
+ logger.LogError("NetworkConnection.ValidatePacketSize: cannot send zero bytes");
return false;
}
@@ -275,47 +183,11 @@ static bool ValidatePacketSize(ArraySegment segment, int channelId)
// internal because no one except Mirror should send bytes directly to
// the client. they would be detected as a message. send messages instead.
- List singleConnectionId = new List{-1};
- internal virtual bool Send(ArraySegment segment, int channelId = Channels.DefaultReliable)
- {
- if (logNetworkMessages) Debug.Log("ConnectionSend con:" + connectionId + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
-
- // validate packet size first.
- if (ValidatePacketSize(segment, channelId))
- {
- // send to client or server
- if (Transport.activeTransport.ClientConnected())
- {
- return Transport.activeTransport.ClientSend(channelId, segment);
- }
- else if (Transport.activeTransport.ServerActive())
- {
- singleConnectionId[0] = connectionId;
- return Transport.activeTransport.ServerSend(singleConnectionId, channelId, segment);
- }
- }
- return false;
- }
-
- // Send to many. basically Transport.Send(connections) + checks.
- internal static bool Send(List connectionIds, ArraySegment segment, int channelId = Channels.DefaultReliable)
- {
- // validate packet size first.
- if (ValidatePacketSize(segment, channelId))
- {
- // only the server sends to many, we don't have that function on
- // a client.
- if (Transport.activeTransport.ServerActive())
- {
- return Transport.activeTransport.ServerSend(connectionIds, channelId, segment);
- }
- }
- return false;
- }
+ internal abstract bool Send(ArraySegment segment, int channelId = Channels.DefaultReliable);
public override string ToString()
{
- return $"connectionId: {connectionId} isReady: {isReady}";
+ return $"connection({connectionId})";
}
internal void AddToVisList(NetworkIdentity identity)
@@ -346,30 +218,14 @@ internal void RemoveObservers()
visList.Clear();
}
- ///
- /// Obsolete: Use instead
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use InvokeHandler instead")]
- public bool InvokeHandlerNoData(int msgType)
- {
- return InvokeHandler(msgType, null, -1);
- }
-
internal bool InvokeHandler(int msgType, NetworkReader reader, int channelId)
{
if (messageHandlers.TryGetValue(msgType, out NetworkMessageDelegate msgDelegate))
{
- NetworkMessage message = new NetworkMessage
- {
- reader = reader,
- conn = this,
- channelId = channelId
- };
-
- msgDelegate(message);
+ msgDelegate(this, reader, channelId);
return true;
}
- Debug.LogError("Unknown message ID " + msgType + " connId:" + connectionId);
+ if (logger.LogEnabled()) logger.Log("Unknown message ID " + msgType + " " + this + ". May be due to no existing RegisterHandler for this message.");
return false;
}
@@ -379,23 +235,23 @@ internal bool InvokeHandler(int msgType, NetworkReader reader, int channelId)
///
/// The message type to unregister.
/// The message object to process.
- ///
+ /// Returns true if the handler was successfully invoked
public bool InvokeHandler(T msg, int channelId) where T : IMessageBase
{
// get writer from pool
- NetworkWriter writer = NetworkWriterPool.GetWriter();
-
- // pack and invoke
- int msgType = MessagePacker.GetId(msg.GetType());
- MessagePacker.Pack(msg, writer);
- ArraySegment segment = writer.ToArraySegment();
- NetworkReader reader = NetworkReaderPool.GetReader(segment);
- bool result = InvokeHandler(msgType, reader, channelId);
- NetworkReaderPool.Recycle(reader);
-
- // recycle writer and return
- NetworkWriterPool.Recycle(writer);
- return result;
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
+ {
+ // if it is a value type, just use typeof(T) to avoid boxing
+ // this works because value types cannot be derived
+ // if it is a reference type (for example IMessageBase),
+ // ask the message for the real type
+ int msgType = MessagePacker.GetId(default(T) != null ? typeof(T) : msg.GetType());
+
+ MessagePacker.Pack(msg, writer);
+ ArraySegment segment = writer.ToArraySegment();
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(segment))
+ return InvokeHandler(msgType, networkReader, channelId);
+ }
}
// note: original HLAPI HandleBytes function handled >1 message in a while loop, but this wasn't necessary
@@ -405,40 +261,68 @@ public bool InvokeHandler(T msg, int channelId) where T : IMessageBase
// -> can be tested easily with a 1000ms send delay and then logging amount received in while loops here
// and in NetworkServer/Client Update. HandleBytes already takes exactly one.
///
- /// This virtual function allows custom network connection classes to process data from the network before it is passed to the application.
+ /// This function allows custom network connection classes to process data from the network before it is passed to the application.
///
- /// The data recieved.
- public virtual void TransportReceive(ArraySegment buffer, int channelId)
+ /// The data received.
+ internal void TransportReceive(ArraySegment buffer, int channelId)
{
// unpack message
- NetworkReader reader = NetworkReaderPool.GetReader(buffer);
- if (MessagePacker.UnpackMessage(reader, out int msgType))
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(buffer))
{
- // logging
- if (logNetworkMessages) Debug.Log("ConnectionRecv con:" + connectionId + " msgType:" + msgType + " content:" + BitConverter.ToString(buffer.Array, buffer.Offset, buffer.Count));
-
- // try to invoke the handler for that message
- if (InvokeHandler(msgType, reader, channelId))
+ if (MessagePacker.UnpackMessage(networkReader, out int msgType))
{
- lastMessageTime = Time.time;
+ // logging
+ if (logger.LogEnabled()) logger.Log("ConnectionRecv " + this + " msgType:" + msgType + " content:" + BitConverter.ToString(buffer.Array, buffer.Offset, buffer.Count));
+
+ // try to invoke the handler for that message
+ if (InvokeHandler(msgType, networkReader, channelId))
+ {
+ lastMessageTime = Time.time;
+ }
+ }
+ else
+ {
+ logger.LogError("Closed connection: " + this + ". Invalid message header.");
+ Disconnect();
}
}
- else
- {
- Debug.LogError("Closed connection: " + connectionId + ". Invalid message header.");
- Disconnect();
- }
- NetworkReaderPool.Recycle(reader);
+ }
+
+ // Failsafe to kick clients that have stopped sending anything to the server.
+ // Clients Ping the server every 2 seconds but transports are unreliable
+ // when it comes to properly generating Disconnect messages to the server.
+ // This cannot be abstract because then NetworkConnectionToServer
+ // would require and override that would never be called
+ // This is overriden in NetworkConnectionToClient.
+ internal virtual bool IsClientAlive()
+ {
+ return true;
}
internal void AddOwnedObject(NetworkIdentity obj)
{
- clientOwnedObjects.Add(obj.netId);
+ clientOwnedObjects.Add(obj);
}
internal void RemoveOwnedObject(NetworkIdentity obj)
{
- clientOwnedObjects.Remove(obj.netId);
+ clientOwnedObjects.Remove(obj);
+ }
+
+ internal void DestroyOwnedObjects()
+ {
+ // create a copy because the list might be modified when destroying
+ HashSet tmp = new HashSet(clientOwnedObjects);
+ foreach (NetworkIdentity netIdentity in tmp)
+ {
+ if (netIdentity != null)
+ {
+ NetworkServer.Destroy(netIdentity.gameObject);
+ }
+ }
+
+ // clear the hashset because we destroyed them all
+ clientOwnedObjects.Clear();
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToClient.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToClient.cs
new file mode 100644
index 0000000..8f20279
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToClient.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Mirror
+{
+ public class NetworkConnectionToClient : NetworkConnection
+ {
+ static readonly ILogger logger = LogFactory.GetLogger();
+
+ public NetworkConnectionToClient(int networkConnectionId) : base(networkConnectionId) { }
+
+ public override string address => Transport.activeTransport.ServerGetClientAddress(connectionId);
+
+ // internal because no one except Mirror should send bytes directly to
+ // the client. they would be detected as a message. send messages instead.
+ readonly List singleConnectionId = new List { -1 };
+
+ // Failsafe to kick clients that have stopped sending anything to the server.
+ // Clients ping the server every 2 seconds but transports are unreliable
+ // when it comes to properly generating Disconnect messages to the server.
+ internal override bool IsClientAlive() => Time.time - lastMessageTime < NetworkServer.disconnectInactiveTimeout;
+
+ internal override bool Send(ArraySegment segment, int channelId = Channels.DefaultReliable)
+ {
+ if (logger.LogEnabled()) logger.Log("ConnectionSend " + this + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
+
+ // validate packet size first.
+ if (ValidatePacketSize(segment, channelId))
+ {
+ singleConnectionId[0] = connectionId;
+ return Transport.activeTransport.ServerSend(singleConnectionId, channelId, segment);
+ }
+ return false;
+ }
+
+ // Send to many. basically Transport.Send(connections) + checks.
+ internal static bool Send(List connectionIds, ArraySegment segment, int channelId = Channels.DefaultReliable)
+ {
+ // validate packet size first.
+ if (ValidatePacketSize(segment, channelId))
+ {
+ // only the server sends to many, we don't have that function on
+ // a client.
+ if (Transport.activeTransport.ServerActive())
+ {
+ return Transport.activeTransport.ServerSend(connectionIds, channelId, segment);
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Disconnects this connection.
+ ///
+ public override void Disconnect()
+ {
+ // set not ready and handle clientscene disconnect in any case
+ // (might be client or host mode here)
+ isReady = false;
+ Transport.activeTransport.ServerDisconnect(connectionId);
+ RemoveObservers();
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToClient.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToClient.cs.meta
new file mode 100644
index 0000000..75bb702
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToClient.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bb2195f8b29d24f0680a57fde2e9fd09
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToServer.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToServer.cs
new file mode 100644
index 0000000..3e2f22f
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToServer.cs
@@ -0,0 +1,36 @@
+using System;
+using UnityEngine;
+
+namespace Mirror
+{
+ public class NetworkConnectionToServer : NetworkConnection
+ {
+ static readonly ILogger logger = LogFactory.GetLogger();
+
+ public override string address => "";
+
+ internal override bool Send(ArraySegment segment, int channelId = Channels.DefaultReliable)
+ {
+ if (logger.LogEnabled()) logger.Log("ConnectionSend " + this + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
+
+ // validate packet size first.
+ if (ValidatePacketSize(segment, channelId))
+ {
+ return Transport.activeTransport.ClientSend(channelId, segment);
+ }
+ return false;
+ }
+
+ ///
+ /// Disconnects this connection.
+ ///
+ public override void Disconnect()
+ {
+ // set not ready and handle clientscene disconnect in any case
+ // (might be client or host mode here)
+ isReady = false;
+ ClientScene.HandleClientDisconnect(this);
+ Transport.activeTransport.ClientDisconnect();
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToServer.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToServer.cs.meta
new file mode 100644
index 0000000..7e4a710
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkConnectionToServer.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 761977cbf38a34ded9dd89de45445675
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkDiagnostics.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkDiagnostics.cs
index 5661153..1a785c9 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkDiagnostics.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkDiagnostics.cs
@@ -1,6 +1,4 @@
using System;
-using System.Diagnostics;
-using UnityEngine.Events;
namespace Mirror
{
@@ -67,7 +65,7 @@ internal static void OnSend(T message, int channel, int bytes, int count) whe
/// Subscribe to this if you want to profile the network
///
public static event Action InMessageEvent;
-
+
internal static void OnReceive(T message, int channel, int bytes) where T : IMessageBase
{
if (InMessageEvent != null)
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkIdentity.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkIdentity.cs
index 580af38..f0d74e8 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkIdentity.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkIdentity.cs
@@ -2,8 +2,11 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Security.Cryptography;
+using Mirror.RemoteCalls;
using UnityEngine;
using UnityEngine.Serialization;
+
+
#if UNITY_EDITOR
using UnityEditor;
#if UNITY_2018_3_OR_NEWER
@@ -41,48 +44,50 @@ namespace Mirror
/// * If the dirty mask is non-zero value, then the OnDeserialize function reads the values for the SyncVars that correspond to the dirty bits that are set
/// * If there are SyncVar hook functions, those are invoked with the value read from the stream.
///
- [ExecuteInEditMode]
[DisallowMultipleComponent]
[AddComponentMenu("Network/NetworkIdentity")]
[HelpURL("https://mirror-networking.com/docs/Components/NetworkIdentity.html")]
public sealed class NetworkIdentity : MonoBehaviour
{
+ static readonly ILogger logger = LogFactory.GetLogger();
+
// configuration
- bool m_IsServer;
NetworkBehaviour[] networkBehavioursCache;
- // member used to mark a identity for future reset
- // check MarkForReset for more information.
- bool m_Reset;
-
///
/// Returns true if running as a client and this object was spawned by a server.
///
+ //
+ // IMPORTANT: checking NetworkClient.active means that isClient is false in OnDestroy:
+ // public bool isClient => NetworkClient.active && netId != 0 && !serverOnly;
+ // but we need it in OnDestroy, e.g. when saving skillbars on quit. this
+ // works fine if we keep the UNET way of setting isClient manually.
+ // => fixes https://github.com/vis2k/Mirror/issues/1475
public bool isClient { get; internal set; }
///
/// Returns true if NetworkServer.active and server is not stopped.
///
- public bool isServer
- {
- get => m_IsServer && NetworkServer.active && netId != 0;
- internal set => m_IsServer = value;
- }
+ //
+ // IMPORTANT: checking NetworkServer.active means that isServer is false in OnDestroy:
+ // public bool isServer => NetworkServer.active && netId != 0;
+ // but we need it in OnDestroy, e.g. when saving players on quit. this
+ // works fine if we keep the UNET way of setting isServer manually.
+ // => fixes https://github.com/vis2k/Mirror/issues/1484
+ public bool isServer { get; internal set; }
///
/// This returns true if this object is the one that represents the player on the local machine.
/// This is set when the server has spawned an object for this particular client.
///
- public bool isLocalPlayer { get; private set; }
-
- internal bool pendingOwner { get; set; }
+ public bool isLocalPlayer => ClientScene.localPlayer == this;
///
- /// This returns true if this object is the authoritative version of the object in the distributed network application.
- /// This value is determined at runtime, as opposed to localPlayerAuthority which is set on the prefab. For most objects, authority is held by the server / host. For objects with localPlayerAuthority set, authority is held by the client of that player.
+ /// This returns true if this object is the authoritative player object on the client.
+ /// This value is determined at runtime. For most objects, authority is held by the server.
/// For objects that had their authority set by AssignClientAuthority on the server, this will be true on the client that owns the object. NOT on other clients.
///
- public bool hasAuthority { get; private set; }
+ public bool hasAuthority { get; internal set; }
///
/// The set of network connections (players) that can see this object.
@@ -100,7 +105,9 @@ public bool isServer
/// A unique identifier for NetworkIdentity objects within a scene.
/// This is used for spawning scene objects on clients.
///
- public ulong sceneId => m_SceneId;
+ // persistent scene id (see AssignSceneID comments)
+ [FormerlySerializedAs("m_SceneId"), HideInInspector]
+ public ulong sceneId;
///
/// Flag to make this object only exist when the game is running as a server (or host).
@@ -108,38 +115,75 @@ public bool isServer
[FormerlySerializedAs("m_ServerOnly")]
public bool serverOnly;
- ///
- /// localPlayerAuthority means that the client of the "owning" player has authority over their own player object.
- /// Authority for this object will be on the player's client. So hasAuthority will be true on that client - and false on the server and on other clients.
- ///
- [FormerlySerializedAs("m_LocalPlayerAuthority")]
- public bool localPlayerAuthority;
-
- ///
- /// The client that has authority for this object. This will be null if no client has authority.
- /// This is set for player objects with localPlayerAuthority, and for objects set with AssignClientAuthority, and spawned with SpawnWithClientAuthority.
- ///
- public NetworkConnection clientAuthorityOwner { get; internal set; }
-
///
/// The NetworkConnection associated with this NetworkIdentity. This is only valid for player objects on a local client.
///
public NetworkConnection connectionToServer { get; internal set; }
+ NetworkConnectionToClient _connectionToClient;
+
///
- /// The NetworkConnection associated with this NetworkIdentity. This is only valid for player objects on the server.
+ /// The NetworkConnection associated with this NetworkIdentity. This is valid for player and other owned objects in the server.
/// Use it to return details such as the connection's identity, IP address and ready status.
///
- public NetworkConnection connectionToClient { get; internal set; }
+ public NetworkConnectionToClient connectionToClient
+ {
+ get => _connectionToClient;
+
+ internal set
+ {
+ if (_connectionToClient != null)
+ _connectionToClient.RemoveOwnedObject(this);
+
+ _connectionToClient = value;
+ _connectionToClient?.AddOwnedObject(this);
+ }
+ }
///
/// All spawned NetworkIdentities by netId. Available on server and client.
///
public static readonly Dictionary spawned = new Dictionary();
- public NetworkBehaviour[] NetworkBehaviours => networkBehavioursCache = networkBehavioursCache ?? GetComponents();
+ public NetworkBehaviour[] NetworkBehaviours
+ {
+ get
+ {
+ if (networkBehavioursCache == null)
+ {
+ CreateNetworkBehavioursCache();
+ }
+ return networkBehavioursCache;
+ }
+ }
- [SerializeField] string m_AssetId;
+ void CreateNetworkBehavioursCache()
+ {
+ networkBehavioursCache = GetComponents();
+ if (NetworkBehaviours.Length > 64)
+ {
+ logger.LogError($"Only 64 NetworkBehaviour components are allowed for NetworkIdentity: {name} because of the dirtyComponentMask", this);
+ // Log error once then resize array so that NetworkIdentity does not throw exceptions later
+ Array.Resize(ref networkBehavioursCache, 64);
+ }
+ }
+
+
+ // NetworkProximityChecker caching
+ NetworkVisibility visibilityCache;
+ public NetworkVisibility visibility
+ {
+ get
+ {
+ if (visibilityCache == null)
+ {
+ visibilityCache = GetComponent();
+ }
+ return visibilityCache;
+ }
+ }
+
+ [SerializeField, HideInInspector] string m_AssetId;
// the AssetId trick:
// - ideally we would have a serialized 'Guid m_AssetId' but Unity can't
@@ -168,55 +212,58 @@ public Guid assetId
}
internal set
{
- string newAssetIdString = value.ToString("N");
- if (string.IsNullOrEmpty(m_AssetId) || m_AssetId == newAssetIdString)
+ string newAssetIdString = value == Guid.Empty ? string.Empty : value.ToString("N");
+ string oldAssetIdSrting = m_AssetId;
+
+ // they are the same, do nothing
+ if (oldAssetIdSrting == newAssetIdString)
{
- m_AssetId = newAssetIdString;
+ return;
}
- else Debug.LogWarning("SetDynamicAssetId object already has an assetId <" + m_AssetId + ">");
+
+ // new is empty
+ if (string.IsNullOrEmpty(newAssetIdString))
+ {
+ logger.LogError($"Can not set AssetId to empty guid on NetworkIdentity '{name}', old assetId '{oldAssetIdSrting}'");
+ return;
+ }
+
+ // old not empty
+ if (!string.IsNullOrEmpty(oldAssetIdSrting))
+ {
+ logger.LogError($"Can not Set AssetId on NetworkIdentity '{name}' becasue it already had an assetId, current assetId '{oldAssetIdSrting}', attempted new assetId '{newAssetIdString}'");
+ return;
+ }
+
+ // old is empty
+ m_AssetId = newAssetIdString;
+
+ if (logger.LogEnabled()) logger.Log($"Settings AssetId on NetworkIdentity '{name}', new assetId '{newAssetIdString}'");
}
}
- // persistent scene id
- // (see AssignSceneID comments)
- // suppress "Field 'NetworkIdentity.m_SceneId' is never assigned to, and will always have its default value 0"
- // when building standalone
-#pragma warning disable CS0649
- [SerializeField] ulong m_SceneId;
-#pragma warning restore CS0649
-
// keep track of all sceneIds to detect scene duplicates
static readonly Dictionary sceneIds = new Dictionary();
- public NetworkIdentity GetSceneIdenity(ulong id) => sceneIds[id];
+ ///
+ /// Gets the NetworkIdentity from the sceneIds dictionary with the corresponding id
+ ///
+ ///
+ /// NetworkIdentity from the sceneIds dictionary
+ public static NetworkIdentity GetSceneIdentity(ulong id) => sceneIds[id];
// used when adding players
internal void SetClientOwner(NetworkConnection conn)
{
- if (clientAuthorityOwner != null)
- {
- Debug.LogError("SetClientOwner m_ClientAuthorityOwner already set!");
- }
- clientAuthorityOwner = conn;
- clientAuthorityOwner.AddOwnedObject(this);
- }
-
- internal void ForceAuthority(bool authority)
- {
- if (hasAuthority == authority)
+ // do nothing if it already has an owner
+ if (connectionToClient != null && conn != connectionToClient)
{
+ logger.LogError($"Object {this} netId={netId} already has an owner. Use RemoveClientAuthority() first", this);
return;
}
- hasAuthority = authority;
- if (authority)
- {
- OnStartAuthority();
- }
- else
- {
- OnStopAuthority();
- }
+ // otherwise set the owner connection
+ connectionToClient = (NetworkConnectionToClient)conn;
}
static uint nextNetworkId = 1;
@@ -228,78 +275,50 @@ internal void ForceAuthority(bool authority)
public static void ResetNextNetworkId() => nextNetworkId = 1;
///
- /// Obsolete: Host Migration was removed
+ /// The delegate type for the clientAuthorityCallback.
///
/// The network connection that is gaining or losing authority.
/// The object whose client authority status is being changed.
/// The new state of client authority of the object for the connection.
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Host Migration was removed")]
public delegate void ClientAuthorityCallback(NetworkConnection conn, NetworkIdentity identity, bool authorityState);
///
- /// Obsolete: Host Migration was removed
- /// Whenever an object is spawned using SpawnWithClientAuthority, or the client authority status of an object is changed with AssignClientAuthority or RemoveClientAuthority, then this callback will be invoked.
- /// This callback is used by the NetworkMigrationManager to distribute client authority state to peers for host migration. If the NetworkMigrationManager is not being used, this callback does not need to be populated.
+ /// A callback that can be populated to be notified when the client-authority state of objects changes.
+ /// Whenever an object is spawned with client authority, or the client authority status of an object is changed with AssignClientAuthority or RemoveClientAuthority, then this callback will be invoked.
+ /// This callback is only invoked on the server.
///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Host Migration was removed")]
public static ClientAuthorityCallback clientAuthorityCallback;
- // used when the player object for a connection changes
- internal void SetNotLocalPlayer()
- {
- isLocalPlayer = false;
-
- if (NetworkServer.active && NetworkServer.localClientActive)
- {
- // dont change authority for objects on the host
- return;
- }
- hasAuthority = false;
- }
-
// this is used when a connection is destroyed, since the "observers" property is read-only
internal void RemoveObserverInternal(NetworkConnection conn)
{
observers?.Remove(conn.connectionId);
}
+ // hasSpawned should always be false before runtime
+ [SerializeField, HideInInspector] bool hasSpawned;
+ public bool SpawnedFromInstantiate { get; private set; }
+
void Awake()
{
- // detect runtime sceneId duplicates, e.g. if a user tries to
- // Instantiate a sceneId object at runtime. if we don't detect it,
- // then the client won't know which of the two objects to use for a
- // SpawnSceneObject message, and it's likely going to be the wrong
- // object.
- //
- // This might happen if for example we have a Dungeon GameObject
- // which contains a Skeleton monster as child, and when a player
- // runs into the Dungeon we create a Dungeon Instance of that
- // Dungeon, which would duplicate a scene object.
- //
- // see also: https://github.com/vis2k/Mirror/issues/384
- if (Application.isPlaying && sceneId != 0)
+ if (hasSpawned)
{
- if (sceneIds.TryGetValue(sceneId, out NetworkIdentity existing) && existing != this)
- {
- Debug.LogError(name + "'s sceneId: " + sceneId.ToString("X") + " is already taken by: " + existing.name + ". Don't call Instantiate for NetworkIdentities that were in the scene since the beginning (aka scene objects). Otherwise the client won't know which object to use for a SpawnSceneObject message.");
- Destroy(gameObject);
- }
- else
- {
- sceneIds[sceneId] = this;
- }
+ logger.LogError($"{name} has already spawned. Don't call Instantiate for NetworkIdentities that were in the scene since the beginning (aka scene objects). Otherwise the client won't know which object to use for a SpawnSceneObject message.");
+
+ SpawnedFromInstantiate = true;
+ Destroy(gameObject);
}
+
+ hasSpawned = true;
}
void OnValidate()
{
-#if UNITY_EDITOR
- if (serverOnly && localPlayerAuthority)
- {
- Debug.LogWarning("Disabling Local Player Authority for " + gameObject + " because it is server-only.");
- localPlayerAuthority = false;
- }
+ // OnValidate is not called when using Instantiate, so we can use
+ // it to make sure that hasSpawned is false
+ hasSpawned = false;
+#if UNITY_EDITOR
SetupIDs();
#endif
}
@@ -322,7 +341,7 @@ bool ThisIsASceneObjectWithPrefabParent(out GameObject prefab)
if (prefab == null)
{
- Debug.LogError("Failed to find prefab parent for scene object [name:" + gameObject.name + "]");
+ logger.LogError("Failed to find prefab parent for scene object [name:" + gameObject.name + "]");
return false;
}
return true;
@@ -392,11 +411,11 @@ void AssignSceneID()
return;
// no valid sceneId yet, or duplicate?
- bool duplicate = sceneIds.TryGetValue(m_SceneId, out NetworkIdentity existing) && existing != null && existing != this;
- if (m_SceneId == 0 || duplicate)
+ bool duplicate = sceneIds.TryGetValue(sceneId, out NetworkIdentity existing) && existing != null && existing != this;
+ if (sceneId == 0 || duplicate)
{
// clear in any case, because it might have been a duplicate
- m_SceneId = 0;
+ sceneId = 0;
// if a scene was never opened and we are building it, then a
// sceneId would be assigned to build but not saved in editor,
@@ -406,7 +425,7 @@ void AssignSceneID()
// => throw an exception to cancel the build and let the user
// know how to fix it!
if (BuildPipeline.isBuildingPlayer)
- throw new Exception("Scene " + gameObject.scene.path + " needs to be opened and resaved before building, because the scene object " + name + " has no valid sceneId yet.");
+ throw new InvalidOperationException("Scene " + gameObject.scene.path + " needs to be opened and resaved before building, because the scene object " + name + " has no valid sceneId yet.");
// if we generate the sceneId then we MUST be sure to set dirty
// in order to save the scene object properly. otherwise it
@@ -424,15 +443,15 @@ void AssignSceneID()
duplicate = sceneIds.TryGetValue(randomId, out existing) && existing != null && existing != this;
if (!duplicate)
{
- m_SceneId = randomId;
- //Debug.Log(name + " in scene=" + gameObject.scene.name + " sceneId assigned to: " + m_SceneId.ToString("X"));
+ sceneId = randomId;
+ //logger.Log(name + " in scene=" + gameObject.scene.name + " sceneId assigned to: " + m_SceneId.ToString("X"));
}
}
// add to sceneIds dict no matter what
// -> even if we didn't generate anything new, because we still need
// existing sceneIds in there to check duplicates
- sceneIds[m_SceneId] = this;
+ sceneIds[sceneId] = this;
}
// copy scene path hash into sceneId for scene objects.
@@ -456,26 +475,48 @@ public void SetSceneIdSceneHashPartInternal()
ulong shiftedHash = (ulong)pathHash << 32;
// OR into scene id
- m_SceneId = (m_SceneId & 0xFFFFFFFF) | shiftedHash;
+ sceneId = (sceneId & 0xFFFFFFFF) | shiftedHash;
// log it. this is incredibly useful to debug sceneId issues.
- if (LogFilter.Debug) Debug.Log(name + " in scene=" + gameObject.scene.name + " scene index hash(" + pathHash.ToString("X") + ") copied into sceneId: " + m_SceneId.ToString("X"));
+ if (logger.LogEnabled()) logger.Log(name + " in scene=" + gameObject.scene.name + " scene index hash(" + pathHash.ToString("X") + ") copied into sceneId: " + sceneId.ToString("X"));
}
void SetupIDs()
{
if (ThisIsAPrefab())
{
- m_SceneId = 0; // force 0 for prefabs
+ // force 0 for prefabs
+ sceneId = 0;
AssignAssetID(gameObject);
}
- // check prefabstage BEFORE SceneObjectWithPrefabParent
- // (fixes https://github.com/vis2k/Mirror/issues/976)
+ // are we currently in prefab editing mode? aka prefab stage
+ // => check prefabstage BEFORE SceneObjectWithPrefabParent
+ // (fixes https://github.com/vis2k/Mirror/issues/976)
+ // => if we don't check GetCurrentPrefabStage and only check
+ // GetPrefabStage(gameObject), then the 'else' case where we
+ // assign a sceneId and clear the assetId would still be
+ // triggered for prefabs. in other words: if we are in prefab
+ // stage, do not bother with anything else ever!
else if (PrefabStageUtility.GetCurrentPrefabStage() != null)
{
- m_SceneId = 0; // force 0 for prefabs
- string path = PrefabStageUtility.GetCurrentPrefabStage().prefabAssetPath;
- AssignAssetID(path);
+ // when modifying a prefab in prefab stage, Unity calls
+ // OnValidate for that prefab and for all scene objects based on
+ // that prefab.
+ //
+ // is this GameObject the prefab that we modify, and not just a
+ // scene object based on the prefab?
+ // * GetCurrentPrefabStage = 'are we editing ANY prefab?'
+ // * GetPrefabStage(go) = 'are we editing THIS prefab?'
+ if (PrefabStageUtility.GetPrefabStage(gameObject) != null)
+ {
+ // force 0 for prefabs
+ sceneId = 0;
+ //logger.Log(name + " @ scene: " + gameObject.scene.name + " sceneid reset to 0 because CurrentPrefabStage=" + PrefabStageUtility.GetCurrentPrefabStage() + " PrefabStage=" + PrefabStageUtility.GetPrefabStage(gameObject));
+ // NOTE: might make sense to use GetPrefabStage for asset
+ // path, but let's not touch it while it works.
+ string path = PrefabStageUtility.GetCurrentPrefabStage().prefabAssetPath;
+ AssignAssetID(path);
+ }
}
else if (ThisIsASceneObjectWithPrefabParent(out GameObject prefab))
{
@@ -490,161 +531,260 @@ void SetupIDs()
}
#endif
+ // Unity will Destroy all networked objects on Scene Change, so we have to handle that here silently.
+ // That means we cannot have any warning or logging in this method.
void OnDestroy()
{
- // remove from sceneIds
- // -> remove with (0xFFFFFFFFFFFFFFFF) and without (0x00000000FFFFFFFF)
- // sceneHash to be 100% safe.
- sceneIds.Remove(sceneId);
- sceneIds.Remove(sceneId & 0x00000000FFFFFFFF);
+ // Objects spawned from Instantiate are not allowed so are destroyed right away
+ // we don't want to call NetworkServer.Destroy if this is the case
+ if (SpawnedFromInstantiate)
+ return;
- if (m_IsServer && NetworkServer.active)
+ // If false the object has already been unspawned
+ // if it is still true, then we need to unspawn it
+ if (isServer)
{
+ // Do not add logging to this (see above)
NetworkServer.Destroy(gameObject);
}
}
- internal void OnStartServer(bool allowNonZeroNetId)
+ internal void OnStartServer()
{
- if (m_IsServer)
- {
+ // do nothing if already spawned
+ if (isServer)
return;
- }
- m_IsServer = true;
- hasAuthority = !localPlayerAuthority;
- observers = new Dictionary();
+ // set isServer flag
+ isServer = true;
// If the instance/net ID is invalid here then this is an object instantiated from a prefab and the server should assign a valid ID
- if (netId == 0)
- {
- netId = GetNextNetworkId();
- }
- else
- {
- if (!allowNonZeroNetId)
- {
- Debug.LogError("Object has non-zero netId " + netId + " for " + gameObject);
- return;
- }
+ // NOTE: this might not be necessary because the above m_IsServer
+ // check already checks netId. BUT this case here checks only
+ // netId, so it would still check cases where isServer=false
+ // but netId!=0.
+ if (netId != 0)
+ {
+ // This object has already been spawned, this method might be called again
+ // if we try to respawn all objects. This can happen when we add a scene
+ // in that case there is nothing else to do.
+ return;
}
- if (LogFilter.Debug) Debug.Log("OnStartServer " + this + " NetId:" + netId + " SceneId:" + sceneId);
+ netId = GetNextNetworkId();
+ observers = new Dictionary();
+
+ if (logger.LogEnabled()) logger.Log("OnStartServer " + this + " NetId:" + netId + " SceneId:" + sceneId);
// add to spawned (note: the original EnableIsServer isn't needed
// because we already set m_isServer=true above)
spawned[netId] = this;
+ // in host mode we set isClient true before calling OnStartServer,
+ // otherwise isClient is false in OnStartServer.
+ if (NetworkClient.active)
+ {
+ isClient = true;
+ }
+
foreach (NetworkBehaviour comp in NetworkBehaviours)
{
+ // an exception in OnStartServer should be caught, so that one
+ // component's exception doesn't stop all other components from
+ // being initialized
+ // => this is what Unity does for Start() etc. too.
+ // one exception doesn't stop all the other Start() calls!
try
{
comp.OnStartServer();
}
catch (Exception e)
{
- Debug.LogError("Exception in OnStartServer:" + e.Message + " " + e.StackTrace);
+ logger.LogError("Exception in OnStartServer:" + e.Message + " " + e.StackTrace);
}
}
+ }
- if (NetworkClient.active && NetworkServer.localClientActive)
- {
- // there will be no spawn message, so start the client here too
- OnStartClient();
- }
-
- if (hasAuthority)
+ internal void OnStopServer()
+ {
+ foreach (NetworkBehaviour comp in NetworkBehaviours)
{
- OnStartAuthority();
+ // an exception in OnStartServer should be caught, so that one
+ // component's exception doesn't stop all other components from
+ // being initialized
+ // => this is what Unity does for Start() etc. too.
+ // one exception doesn't stop all the other Start() calls!
+ try
+ {
+ comp.OnStopServer();
+ }
+ catch (Exception e)
+ {
+ logger.LogError("Exception in OnStopServer:" + e.Message + " " + e.StackTrace);
+ }
}
}
+ bool clientStarted;
internal void OnStartClient()
{
+ if (clientStarted)
+ return;
+ clientStarted = true;
+
isClient = true;
- if (LogFilter.Debug) Debug.Log("OnStartClient " + gameObject + " netId:" + netId + " localPlayerAuthority:" + localPlayerAuthority);
+ if (logger.LogEnabled()) logger.Log("OnStartClient " + gameObject + " netId:" + netId);
foreach (NetworkBehaviour comp in NetworkBehaviours)
{
+ // an exception in OnStartClient should be caught, so that one
+ // component's exception doesn't stop all other components from
+ // being initialized
+ // => this is what Unity does for Start() etc. too.
+ // one exception doesn't stop all the other Start() calls!
try
{
- comp.OnStartClient(); // user implemented startup
+ // user implemented startup
+ comp.OnStartClient();
}
catch (Exception e)
{
- Debug.LogError("Exception in OnStartClient:" + e.Message + " " + e.StackTrace);
+ logger.LogError("Exception in OnStartClient:" + e.Message + " " + e.StackTrace);
}
}
}
- void OnStartAuthority()
+ static NetworkIdentity previousLocalPlayer = null;
+ internal void OnStartLocalPlayer()
{
- if (networkBehavioursCache == null)
- {
- Debug.LogError("Network object " + name + " not initialized properly. Do you have more than one NetworkIdentity in the same object? Did you forget to spawn this object with NetworkServer?", this);
+ if (previousLocalPlayer == this)
return;
+ previousLocalPlayer = this;
+
+ foreach (NetworkBehaviour comp in NetworkBehaviours)
+ {
+ // an exception in OnStartLocalPlayer should be caught, so that
+ // one component's exception doesn't stop all other components
+ // from being initialized
+ // => this is what Unity does for Start() etc. too.
+ // one exception doesn't stop all the other Start() calls!
+ try
+ {
+ comp.OnStartLocalPlayer();
+ }
+ catch (Exception e)
+ {
+ logger.LogError("Exception in OnStartLocalPlayer:" + e.Message + " " + e.StackTrace);
+ }
}
+ }
+
+ bool hadAuthority;
+ internal void NotifyAuthority()
+ {
+ if (!hadAuthority && hasAuthority)
+ OnStartAuthority();
+ if (hadAuthority && !hasAuthority)
+ OnStopAuthority();
+ hadAuthority = hasAuthority;
+ }
+ internal void OnStartAuthority()
+ {
foreach (NetworkBehaviour comp in NetworkBehaviours)
{
+ // an exception in OnStartAuthority should be caught, so that one
+ // component's exception doesn't stop all other components from
+ // being initialized
+ // => this is what Unity does for Start() etc. too.
+ // one exception doesn't stop all the other Start() calls!
try
{
comp.OnStartAuthority();
}
catch (Exception e)
{
- Debug.LogError("Exception in OnStartAuthority:" + e.Message + " " + e.StackTrace);
+ logger.LogError("Exception in OnStartAuthority:" + e.Message + " " + e.StackTrace);
}
}
}
- void OnStopAuthority()
+ internal void OnStopAuthority()
{
foreach (NetworkBehaviour comp in NetworkBehaviours)
{
+ // an exception in OnStopAuthority should be caught, so that one
+ // component's exception doesn't stop all other components from
+ // being initialized
+ // => this is what Unity does for Start() etc. too.
+ // one exception doesn't stop all the other Start() calls!
try
{
comp.OnStopAuthority();
}
catch (Exception e)
{
- Debug.LogError("Exception in OnStopAuthority:" + e.Message + " " + e.StackTrace);
+ logger.LogError("Exception in OnStopAuthority:" + e.Message + " " + e.StackTrace);
}
}
}
- internal void OnSetLocalVisibility(bool vis)
+ internal void OnSetHostVisibility(bool visible)
{
- foreach (NetworkBehaviour comp in NetworkBehaviours)
+ if (visibility != null)
{
try
{
- comp.OnSetLocalVisibility(vis);
+ visibility.OnSetHostVisibility(visible);
}
catch (Exception e)
{
- Debug.LogError("Exception in OnSetLocalVisibility:" + e.Message + " " + e.StackTrace);
+ logger.LogError("Exception in OnSetLocalVisibility:" + e.Message + " " + e.StackTrace);
}
}
}
+ // check if observer can be seen by connection.
+ // * returns true if seen.
+ // * returns true if we have no proximity checker, so by default all are
+ // seen.
internal bool OnCheckObserver(NetworkConnection conn)
{
- foreach (NetworkBehaviour comp in NetworkBehaviours)
+ if (visibility != null)
{
try
{
- if (!comp.OnCheckObserver(conn))
- return false;
+ return visibility.OnCheckObserver(conn);
}
catch (Exception e)
{
- Debug.LogError("Exception in OnCheckObserver:" + e.Message + " " + e.StackTrace);
+ logger.LogError("Exception in OnCheckObserver:" + e.Message + " " + e.StackTrace);
}
}
return true;
}
+ internal void OnStopClient()
+ {
+ foreach (NetworkBehaviour comp in NetworkBehaviours)
+ {
+ // an exception in OnNetworkDestroy should be caught, so that
+ // one component's exception doesn't stop all other components
+ // from being initialized
+ // => this is what Unity does for Start() etc. too.
+ // one exception doesn't stop all the other Start() calls!
+ try
+ {
+ comp.OnStopClient();
+ }
+ catch (Exception e)
+ {
+ logger.LogError("Exception in OnNetworkDestroy:" + e.Message + " " + e.StackTrace);
+ }
+ isServer = false;
+ }
+ }
+
// vis2k: readstring bug prevention: https://issuetracker.unity3d.com/issues/unet-networkwriter-dot-write-causing-readstring-slash-readbytes-out-of-range-errors-in-clients
// -> OnSerialize writes length,componentData,length,componentData,...
// -> OnDeserialize carefully extracts each data, then deserializes each component with separate readers
@@ -668,7 +808,7 @@ bool OnSerializeSafely(NetworkBehaviour comp, NetworkWriter writer, bool initial
catch (Exception e)
{
// show a detailed error and let the user know what went wrong
- Debug.LogError("OnSerialize failed for: object=" + name + " component=" + comp.GetType() + " sceneId=" + m_SceneId.ToString("X") + "\n\n" + e);
+ logger.LogError("OnSerialize failed for: object=" + name + " component=" + comp.GetType() + " sceneId=" + sceneId.ToString("X") + "\n\n" + e);
}
int endPosition = writer.Position;
@@ -677,27 +817,21 @@ bool OnSerializeSafely(NetworkBehaviour comp, NetworkWriter writer, bool initial
writer.WriteInt32(endPosition - contentPosition);
writer.Position = endPosition;
- if (LogFilter.Debug) Debug.Log("OnSerializeSafely written for object=" + comp.name + " component=" + comp.GetType() + " sceneId=" + m_SceneId.ToString("X") + "header@" + headerPosition + " content@" + contentPosition + " end@" + endPosition + " contentSize=" + (endPosition - contentPosition));
+ if (logger.LogEnabled()) logger.Log("OnSerializeSafely written for object=" + comp.name + " component=" + comp.GetType() + " sceneId=" + sceneId.ToString("X") + "header@" + headerPosition + " content@" + contentPosition + " end@" + endPosition + " contentSize=" + (endPosition - contentPosition));
return result;
}
- // serialize all components (or only dirty ones if not initial state)
+ // serialize all components using dirtyComponentsMask
// -> check ownerWritten/observersWritten to know if anything was written
- internal void OnSerializeAllSafely(bool initialState, NetworkWriter ownerWriter, out int ownerWritten, NetworkWriter observersWriter, out int observersWritten)
+ // We pass dirtyComponentsMask into this function so that we can check if any Components are dirty before creating writers
+ internal void OnSerializeAllSafely(bool initialState, ulong dirtyComponentsMask, NetworkWriter ownerWriter, out int ownerWritten, NetworkWriter observersWriter, out int observersWritten)
{
// clear 'written' variables
ownerWritten = observersWritten = 0;
- if (NetworkBehaviours.Length > 64)
- {
- Debug.LogError("Only 64 NetworkBehaviour components are allowed for NetworkIdentity: " + name + " because of the dirtyComponentMask");
- return;
- }
- ulong dirtyComponentsMask = GetDirtyMask(initialState);
-
- if (dirtyComponentsMask == 0L)
- return;
+ // dirtyComponentsMask should be changed before tyhis function is called
+ Debug.Assert(dirtyComponentsMask != 0UL, "OnSerializeAllSafely Should not be given a zero dirtyComponentsMask", this);
// calculate syncMode mask at runtime. this allows users to change
// component.syncMode while the game is running, which can be a huge
@@ -723,7 +857,7 @@ internal void OnSerializeAllSafely(bool initialState, NetworkWriter ownerWriter,
// -> note: IsDirty() is false if the component isn't dirty or sendInterval isn't elapsed yet
if (initialState || comp.IsDirty())
{
- if (LogFilter.Debug) Debug.Log("OnSerializeAllSafely: " + name + " -> " + comp.GetType() + " initial=" + initialState);
+ if (logger.LogEnabled()) logger.Log("OnSerializeAllSafely: " + name + " -> " + comp.GetType() + " initial=" + initialState);
// serialize into ownerWriter first
// (owner always gets everything!)
@@ -751,7 +885,7 @@ internal void OnSerializeAllSafely(bool initialState, NetworkWriter ownerWriter,
}
}
- internal ulong GetDirtyMask(bool initialState)
+ internal ulong GetDirtyComponentsMask()
{
// loop through all components only once and then write dirty+payload into the writer afterwards
ulong dirtyComponentsMask = 0L;
@@ -759,14 +893,26 @@ internal ulong GetDirtyMask(bool initialState)
for (int i = 0; i < components.Length; ++i)
{
NetworkBehaviour comp = components[i];
- if (initialState || comp.IsDirty())
+ if (comp.IsDirty())
{
- dirtyComponentsMask |= (ulong)(1L << i);
+ dirtyComponentsMask |= 1UL << i;
}
}
return dirtyComponentsMask;
}
+ internal ulong GetInitialComponentsMask()
+ {
+ // loop through all components only once and then write dirty+payload into the writer afterwards
+ ulong dirtyComponentsMask = 0UL;
+ for (int i = 0; i < NetworkBehaviours.Length; ++i)
+ {
+ dirtyComponentsMask |= 1UL << i;
+ }
+
+ return dirtyComponentsMask;
+ }
+
// a mask that contains all the components with SyncMode.Observers
internal ulong GetSyncModeObserversMask()
@@ -797,13 +943,18 @@ void OnDeserializeSafely(NetworkBehaviour comp, NetworkReader reader, bool initi
// way to mess up another component's deserialization
try
{
- if (LogFilter.Debug) Debug.Log("OnDeserializeSafely: " + comp.name + " component=" + comp.GetType() + " sceneId=" + m_SceneId.ToString("X") + " length=" + contentSize);
+ if (logger.LogEnabled()) logger.Log("OnDeserializeSafely: " + comp.name + " component=" + comp.GetType() + " sceneId=" + sceneId.ToString("X") + " length=" + contentSize);
comp.OnDeserialize(reader, initialState);
}
catch (Exception e)
{
// show a detailed error and let the user know what went wrong
- Debug.LogError("OnDeserialize failed for: object=" + name + " component=" + comp.GetType() + " sceneId=" + m_SceneId.ToString("X") + " length=" + contentSize + ". Possible Reasons:\n * Do " + comp.GetType() + "'s OnSerialize and OnDeserialize calls write the same amount of data(" + contentSize + " bytes)? \n * Was there an exception in " + comp.GetType() + "'s OnSerialize/OnDeserialize code?\n * Are the server and client the exact same project?\n * Maybe this OnDeserialize call was meant for another GameObject? The sceneIds can easily get out of sync if the Hierarchy was modified only in the client OR the server. Try rebuilding both.\n\n" + e);
+ logger.LogError($"OnDeserialize failed for: object={name} component={comp.GetType()} sceneId={sceneId.ToString("X")} length={contentSize}. Possible Reasons:\n" +
+ $" * Do {comp.GetType()}'s OnSerialize and OnDeserialize calls write the same amount of data({contentSize} bytes)? \n" +
+ $" * Was there an exception in {comp.GetType()}'s OnSerialize/OnDeserialize code?\n" +
+ $" * Are the server and client the exact same project?\n" +
+ $" * Maybe this OnDeserialize call was meant for another GameObject? The sceneIds can easily get out of sync if the Hierarchy was modified only in the client OR the server. Try rebuilding both.\n\n" +
+ $"Exeption {e}");
}
// now the reader should be EXACTLY at 'before + size'.
@@ -812,7 +963,7 @@ void OnDeserializeSafely(NetworkBehaviour comp, NetworkReader reader, bool initi
{
// warn the user
int bytesRead = reader.Position - chunkStart;
- Debug.LogWarning("OnDeserialize was expected to read " + contentSize + " instead of " + bytesRead + " bytes for object:" + name + " component=" + comp.GetType() + " sceneId=" + m_SceneId.ToString("X") + ". Make sure that OnSerialize and OnDeserialize write/read the same amount of data in all cases.");
+ logger.LogWarning("OnDeserialize was expected to read " + contentSize + " instead of " + bytesRead + " bytes for object:" + name + " component=" + comp.GetType() + " sceneId=" + sceneId.ToString("X") + ". Make sure that OnSerialize and OnDeserialize write/read the same amount of data in all cases.");
// fix the position, so the following components don't all fail
reader.Position = chunkEnd;
@@ -829,7 +980,7 @@ internal void OnDeserializeAllSafely(NetworkReader reader, bool initialState)
for (int i = 0; i < components.Length; ++i)
{
// is the dirty bit at position 'i' set to 1?
- ulong dirtyBit = (ulong)(1L << i);
+ ulong dirtyBit = 1UL << i;
if ((dirtyComponentsMask & dirtyBit) != 0L)
{
OnDeserializeSafely(components[i], reader, initialState);
@@ -837,39 +988,28 @@ internal void OnDeserializeAllSafely(NetworkReader reader, bool initialState)
}
}
- // happens on client
- internal void HandleClientAuthority(bool authority)
- {
- if (!localPlayerAuthority)
- {
- Debug.LogError("HandleClientAuthority " + gameObject + " does not have localPlayerAuthority");
- return;
- }
-
- ForceAuthority(authority);
- }
-
// helper function to handle SyncEvent/Command/Rpc
- void HandleRemoteCall(int componentIndex, int functionHash, MirrorInvokeType invokeType, NetworkReader reader)
+ void HandleRemoteCall(int componentIndex, int functionHash, MirrorInvokeType invokeType, NetworkReader reader, NetworkConnectionToClient senderConnection = null)
{
- if (gameObject == null)
+ // check if unity object has been destroyed
+ if (this == null)
{
- Debug.LogWarning(invokeType + " [" + functionHash + "] received for deleted object [netId=" + netId + "]");
+ logger.LogWarning(invokeType + " [" + functionHash + "] received for deleted object [netId=" + netId + "]");
return;
}
// find the right component to invoke the function on
- if (0 <= componentIndex && componentIndex < networkBehavioursCache.Length)
+ if (0 <= componentIndex && componentIndex < NetworkBehaviours.Length)
{
- NetworkBehaviour invokeComponent = networkBehavioursCache[componentIndex];
- if (!invokeComponent.InvokeHandlerDelegate(functionHash, invokeType, reader))
+ NetworkBehaviour invokeComponent = NetworkBehaviours[componentIndex];
+ if (!RemoteCallHelper.InvokeHandlerDelegate(functionHash, invokeType, reader, invokeComponent, senderConnection))
{
- Debug.LogError("Found no receiver for incoming " + invokeType + " [" + functionHash + "] on " + gameObject + ", the server and client should have the same NetworkBehaviour instances [netId=" + netId + "].");
+ logger.LogError("Found no receiver for incoming " + invokeType + " [" + functionHash + "] on " + gameObject + ", the server and client should have the same NetworkBehaviour instances [netId=" + netId + "].");
}
}
else
{
- Debug.LogWarning("Component [" + componentIndex + "] not found for [netId=" + netId + "]");
+ logger.LogWarning("Component [" + componentIndex + "] not found for [netId=" + netId + "]");
}
}
@@ -880,55 +1020,38 @@ internal void HandleSyncEvent(int componentIndex, int eventHash, NetworkReader r
}
// happens on server
- internal void HandleCommand(int componentIndex, int cmdHash, NetworkReader reader)
+ internal void HandleCommand(int componentIndex, int cmdHash, NetworkReader reader, NetworkConnectionToClient senderConnection)
{
- HandleRemoteCall(componentIndex, cmdHash, MirrorInvokeType.Command, reader);
+ HandleRemoteCall(componentIndex, cmdHash, MirrorInvokeType.Command, reader, senderConnection);
}
- // happens on client
- internal void HandleRPC(int componentIndex, int rpcHash, NetworkReader reader)
- {
- HandleRemoteCall(componentIndex, rpcHash, MirrorInvokeType.ClientRpc, reader);
- }
-
- internal void OnUpdateVars(NetworkReader reader, bool initialState)
- {
- OnDeserializeAllSafely(reader, initialState);
- }
-
- internal void SetLocalPlayer()
+ // happens on server
+ internal CommandInfo GetCommandInfo(int componentIndex, int cmdHash)
{
- isLocalPlayer = true;
-
- // There is an ordering issue here that originAuthority solves:
- // OnStartAuthority should only be called if hasAuthority was false when this function began,
- // or it will be called twice for this object, but that state is lost by the time OnStartAuthority
- // is called below, so the original value is cached here to be checked below.
- bool originAuthority = hasAuthority;
- if (localPlayerAuthority)
+ // check if unity object has been destroyed
+ if (this == null)
{
- hasAuthority = true;
+ // error can be logged later
+ return default;
}
- foreach (NetworkBehaviour comp in networkBehavioursCache)
+ // find the right component to invoke the function on
+ if (0 <= componentIndex && componentIndex < NetworkBehaviours.Length)
{
- comp.OnStartLocalPlayer();
-
- if (localPlayerAuthority && !originAuthority)
- {
- comp.OnStartAuthority();
- }
+ NetworkBehaviour invokeComponent = NetworkBehaviours[componentIndex];
+ return RemoteCallHelper.GetCommandInfo(cmdHash, invokeComponent);
+ }
+ else
+ {
+ // error can be logged later
+ return default;
}
}
- internal void OnNetworkDestroy()
+ // happens on client
+ internal void HandleRPC(int componentIndex, int rpcHash, NetworkReader reader)
{
- for (int i = 0; networkBehavioursCache != null && i < networkBehavioursCache.Length; i++)
- {
- NetworkBehaviour comp = networkBehavioursCache[i];
- comp.OnNetworkDestroy();
- }
- m_IsServer = false;
+ HandleRemoteCall(componentIndex, rpcHash, MirrorInvokeType.ClientRpc, reader);
}
internal void ClearObservers()
@@ -947,7 +1070,7 @@ internal void AddObserver(NetworkConnection conn)
{
if (observers == null)
{
- Debug.LogError("AddObserver for " + gameObject + " observer list is null");
+ logger.LogError("AddObserver for " + gameObject + " observer list is null");
return;
}
@@ -958,12 +1081,50 @@ internal void AddObserver(NetworkConnection conn)
return;
}
- if (LogFilter.Debug) Debug.Log("Added observer " + conn.address + " added for " + gameObject);
+ if (logger.LogEnabled()) logger.Log("Added observer " + conn.address + " added for " + gameObject);
observers[conn.connectionId] = conn;
conn.AddToVisList(this);
}
+ // helper function to call OnRebuildObservers in all components
+ // -> HashSet is passed in so we can cache it!
+ // -> returns true if we have a proxchecker, false otherwise
+ // -> initialize is true on first rebuild, false on consecutive rebuilds
+ internal bool GetNewObservers(HashSet observersSet, bool initialize)
+ {
+ observersSet.Clear();
+
+ if (visibility != null)
+ {
+ visibility.OnRebuildObservers(observersSet, initialize);
+ return true;
+ }
+
+ // we have no proximity checker. return false to indicate that we
+ // should use the default implementation.
+ return false;
+ }
+
+ // helper function to add all server connections as observers.
+ // this is used if none of the components provides their own
+ // OnRebuildObservers function.
+ internal void AddAllReadyServerConnectionsToObservers()
+ {
+ // add all server connections
+ foreach (NetworkConnection conn in NetworkServer.connections.Values)
+ {
+ if (conn.isReady)
+ AddObserver(conn);
+ }
+
+ // add local host connection (if any)
+ if (NetworkServer.localConnection != null && NetworkServer.localConnection.isReady)
+ {
+ AddObserver(NetworkServer.localConnection);
+ }
+ }
+
static readonly HashSet newObservers = new HashSet();
///
@@ -972,19 +1133,14 @@ internal void AddObserver(NetworkConnection conn)
/// True if this is the first time.
public void RebuildObservers(bool initialize)
{
+ // observers are null until OnStartServer creates them
if (observers == null)
return;
bool changed = false;
- bool result = false;
- newObservers.Clear();
-
- // call OnRebuildObservers function in components
- foreach (NetworkBehaviour comp in NetworkBehaviours)
- {
- result |= comp.OnRebuildObservers(newObservers, initialize);
- }
+ // call OnRebuildObservers function
+ bool rebuildOverwritten = GetNewObservers(newObservers, initialize);
// if player connection: ensure player always see himself no matter what.
// -> fixes https://github.com/vis2k/Mirror/issues/692 where a
@@ -996,229 +1152,217 @@ public void RebuildObservers(bool initialize)
}
// if no component implemented OnRebuildObservers, then add all
- // connections.
- if (!result)
+ // server connections.
+ if (!rebuildOverwritten)
{
+ // only add all connections when rebuilding the first time.
+ // second time we just keep them without rebuilding anything.
if (initialize)
{
- foreach (NetworkConnection conn in NetworkServer.connections.Values)
- {
- if (conn.isReady)
- AddObserver(conn);
- }
-
- if (NetworkServer.localConnection != null && NetworkServer.localConnection.isReady)
- {
- AddObserver(NetworkServer.localConnection);
- }
+ AddAllReadyServerConnectionsToObservers();
}
return;
}
- // apply changes from rebuild
+ // add all newObservers that aren't in .observers yet
foreach (NetworkConnection conn in newObservers)
{
- if (conn == null)
- {
- continue;
- }
-
- if (!conn.isReady)
- {
- if (LogFilter.Debug) Debug.Log("Observer is not ready for " + gameObject + " " + conn);
- continue;
- }
-
- if (initialize || !observers.ContainsKey(conn.connectionId))
+ // only add ready connections.
+ // otherwise the player might not be in the world yet or anymore
+ if (conn != null && conn.isReady)
{
- // new observer
- conn.AddToVisList(this);
- if (LogFilter.Debug) Debug.Log("New Observer for " + gameObject + " " + conn);
- changed = true;
+ if (initialize || !observers.ContainsKey(conn.connectionId))
+ {
+ // new observer
+ conn.AddToVisList(this);
+ if (logger.LogEnabled()) logger.Log("New Observer for " + gameObject + " " + conn);
+ changed = true;
+ }
}
}
+ // remove all old .observers that aren't in newObservers anymore
foreach (NetworkConnection conn in observers.Values)
{
if (!newObservers.Contains(conn))
{
// removed observer
conn.RemoveFromVisList(this, false);
- if (LogFilter.Debug) Debug.Log("Removed Observer for " + gameObject + " " + conn);
+ if (logger.LogEnabled()) logger.Log("Removed Observer for " + gameObject + " " + conn);
changed = true;
}
}
- // special case for local client.
- if (initialize)
- {
- if (!newObservers.Contains(NetworkServer.localConnection))
- {
- OnSetLocalVisibility(false);
- }
- }
-
if (changed)
{
observers.Clear();
foreach (NetworkConnection conn in newObservers)
{
- if (conn.isReady)
+ if (conn != null && conn.isReady)
observers.Add(conn.connectionId, conn);
}
}
- }
- ///
- /// Obsolete: Use instead
- ///
- /// The connection of the client to remove authority for.
- /// True if authority is removed.
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("NetworkConnection parameter is no longer needed and nothing is returned")]
- public bool RemoveClientAuthority(NetworkConnection conn)
- {
- RemoveClientAuthority();
- return true;
+ // special case for host mode: we use SetHostVisibility to hide
+ // NetworkIdentities that aren't in observer range from host.
+ // this is what games like Dota/Counter-Strike do too, where a host
+ // does NOT see all players by default. they are in memory, but
+ // hidden to the host player.
+ //
+ // this code is from UNET, it's a bit strange but it works:
+ // * it hides newly connected identities in host mode
+ // => that part was the intended behaviour
+ // * it hides ALL NetworkIdentities in host mode when the host
+ // connects but hasn't selected a character yet
+ // => this only works because we have no .localConnection != null
+ // check. at this stage, localConnection is null because
+ // StartHost starts the server first, then calls this code,
+ // then starts the client and sets .localConnection. so we can
+ // NOT add a null check without breaking host visibility here.
+ // * it hides ALL NetworkIdentities in server-only mode because
+ // observers never contain the 'null' .localConnection
+ // => that was not intended, but let's keep it as it is so we
+ // don't break anything in host mode. it's way easier than
+ // iterating all identities in a special function in StartHost.
+ if (initialize)
+ {
+ if (!newObservers.Contains(NetworkServer.localConnection))
+ {
+ OnSetHostVisibility(false);
+ }
+ }
}
///
- /// Removes ownership for an object.
- /// This applies to objects that had authority set by AssignClientAuthority, or NetworkServer.SpawnWithClientAuthority.
- /// Authority cannot be removed for player objects.
+ /// Assign control of an object to a client via the client's NetworkConnection.
+ /// This causes hasAuthority to be set on the client that owns the object, and NetworkBehaviour.OnStartAuthority will be called on that client. This object then will be in the NetworkConnection.clientOwnedObjects list for the connection.
+ /// Authority can be removed with RemoveClientAuthority. Only one client can own an object at any time. This does not need to be called for player objects, as their authority is setup automatically.
///
- public void RemoveClientAuthority()
+ /// The connection of the client to assign authority to.
+ /// True if authority was assigned.
+ public bool AssignClientAuthority(NetworkConnection conn)
{
if (!isServer)
{
- Debug.LogError("RemoveClientAuthority can only be call on the server for spawned objects.");
- return;
+ logger.LogError("AssignClientAuthority can only be called on the server for spawned objects.");
+ return false;
}
- if (connectionToClient != null)
+ if (conn == null)
{
- Debug.LogError("RemoveClientAuthority cannot remove authority for a player object");
- return;
+ logger.LogError("AssignClientAuthority for " + gameObject + " owner cannot be null. Use RemoveClientAuthority() instead.");
+ return false;
}
- if (clientAuthorityOwner != null)
+ if (connectionToClient != null && conn != connectionToClient)
{
- // send msg to that client
- ClientAuthorityMessage msg = new ClientAuthorityMessage
- {
- netId = netId,
- authority = false
- };
-
- clientAuthorityOwner.Send(msg);
-#pragma warning disable CS0618 // Type or member is obsolete
- clientAuthorityCallback?.Invoke(clientAuthorityOwner, this, false);
-#pragma warning restore CS0618 // Type or member is obsolete
+ logger.LogError("AssignClientAuthority for " + gameObject + " already has an owner. Use RemoveClientAuthority() first.");
+ return false;
}
- clientAuthorityOwner.RemoveOwnedObject(this);
- clientAuthorityOwner = null;
+ SetClientOwner(conn);
+
+ // The client will match to the existing object
+ // update all variables and assign authority
+ NetworkServer.SendSpawnMessage(this, conn);
+
+ clientAuthorityCallback?.Invoke(conn, this, true);
- // server now has authority (this is only called on server)
- ForceAuthority(true);
+ return true;
}
///
- /// Assign control of an object to a client via the client's NetworkConnection.
- /// This causes hasAuthority to be set on the client that owns the object, and NetworkBehaviour.OnStartAuthority will be called on that client. This object then will be in the NetworkConnection.clientOwnedObjects list for the connection.
- /// Authority can be removed with RemoveClientAuthority. Only one client can own an object at any time. Only NetworkIdentities with localPlayerAuthority set can have client authority assigned. This does not need to be called for player objects, as their authority is setup automatically.
+ /// Removes ownership for an object.
+ /// This applies to objects that had authority set by AssignClientAuthority, or NetworkServer.Spawn with a NetworkConnection parameter included.
+ /// Authority cannot be removed for player objects.
///
- /// The connection of the client to assign authority to.
- /// True if authority was assigned.
- public bool AssignClientAuthority(NetworkConnection conn)
+ public void RemoveClientAuthority()
{
if (!isServer)
{
- Debug.LogError("AssignClientAuthority can only be called on the server for spawned objects.");
- return false;
- }
- if (!localPlayerAuthority)
- {
- Debug.LogError("AssignClientAuthority can only be used for NetworkIdentity components with LocalPlayerAuthority set.");
- return false;
+ logger.LogError("RemoveClientAuthority can only be called on the server for spawned objects.");
+ return;
}
- if (clientAuthorityOwner != null && conn != clientAuthorityOwner)
+ if (connectionToClient?.identity == this)
{
- Debug.LogError("AssignClientAuthority for " + gameObject + " already has an owner. Use RemoveClientAuthority() first.");
- return false;
+ logger.LogError("RemoveClientAuthority cannot remove authority for a player object");
+ return;
}
- if (conn == null)
+ if (connectionToClient != null)
{
- Debug.LogError("AssignClientAuthority for " + gameObject + " owner cannot be null. Use RemoveClientAuthority() instead.");
- return false;
- }
+ clientAuthorityCallback?.Invoke(connectionToClient, this, false);
- clientAuthorityOwner = conn;
- clientAuthorityOwner.AddOwnedObject(this);
+ NetworkConnectionToClient previousOwner = connectionToClient;
- // server no longer has authority (this is called on server). Note that local client could re-acquire authority below
- ForceAuthority(false);
+ connectionToClient = null;
- // send msg to that client
- ClientAuthorityMessage msg = new ClientAuthorityMessage
- {
- netId = netId,
- authority = true
- };
- conn.Send(msg);
+ // we need to resynchronize the entire object
+ // so just spawn it again,
+ // the client will not create a new instance, it will simply
+ // reset all variables and remove authority
+ NetworkServer.SendSpawnMessage(this, previousOwner);
-#pragma warning disable CS0618 // Type or member is obsolete
- clientAuthorityCallback?.Invoke(conn, this, true);
-#pragma warning restore CS0618 // Type or member is obsolete
- return true;
+ connectionToClient = null;
+ }
}
// marks the identity for future reset, this is because we cant reset the identity during destroy
// as people might want to be able to read the members inside OnDestroy(), and we have no way
// of invoking reset after OnDestroy is called.
- internal void MarkForReset() => m_Reset = true;
-
- // if we have marked an identity for reset we do the actual reset.
internal void Reset()
{
- if (!m_Reset)
- return;
+ // make sure to call this before networkBehavioursCache is cleared below
+ ResetSyncObjects();
- m_Reset = false;
- m_IsServer = false;
+ hasSpawned = false;
+ clientStarted = false;
isClient = false;
- hasAuthority = false;
+ isServer = false;
netId = 0;
- isLocalPlayer = false;
connectionToServer = null;
connectionToClient = null;
networkBehavioursCache = null;
ClearObservers();
- clientAuthorityOwner = null;
}
- // MirrorUpdate is a hot path. Caching the vars msg is really worth it to
- // avoid large amounts of allocations.
- static UpdateVarsMessage varsMessage = new UpdateVarsMessage();
-
// invoked by NetworkServer during Update()
- internal void MirrorUpdate()
+ internal void ServerUpdate()
{
if (observers != null && observers.Count > 0)
{
- // one writer for owner, one for observers
- NetworkWriter ownerWriter = NetworkWriterPool.GetWriter();
- NetworkWriter observersWriter = NetworkWriterPool.GetWriter();
+ ulong dirtyComponentsMask = GetDirtyComponentsMask();
- // serialize all the dirty components and send (if any were dirty)
- OnSerializeAllSafely(false, ownerWriter, out int ownerWritten, observersWriter, out int observersWritten);
+ // AnyComponentsDirty
+ if (dirtyComponentsMask != 0UL)
+ {
+ SendUpdateVarsMessage(dirtyComponentsMask);
+ }
+ }
+ else
+ {
+ // clear all component's dirty bits.
+ // it would be spawned on new observers anyway.
+ ClearAllComponentsDirtyBits();
+ }
+ }
+
+ void SendUpdateVarsMessage(ulong dirtyComponentsMask)
+ {
+ // one writer for owner, one for observers
+ using (PooledNetworkWriter ownerWriter = NetworkWriterPool.GetWriter(), observersWriter = NetworkWriterPool.GetWriter())
+ {
+ // serialize all the dirty components and send
+ OnSerializeAllSafely(false, dirtyComponentsMask, ownerWriter, out int ownerWritten, observersWriter, out int observersWritten);
if (ownerWritten > 0 || observersWritten > 0)
{
- // populate cached UpdateVarsMessage and send
- varsMessage.netId = netId;
+ UpdateVarsMessage varsMessage = new UpdateVarsMessage
+ {
+ netId = netId
+ };
// send ownerWriter to owner
// (only if we serialized anything for owner)
@@ -1249,16 +1393,10 @@ internal void MirrorUpdate()
// them if initialState. clearing the dirty ones is enough.)
ClearDirtyComponentsDirtyBits();
}
- NetworkWriterPool.Recycle(ownerWriter);
- NetworkWriterPool.Recycle(observersWriter);
- }
- else
- {
- // clear all component's dirty bits
- ClearAllComponentsDirtyBits();
}
}
+
// clear all component's dirty bits no matter what
internal void ClearAllComponentsDirtyBits()
{
@@ -1280,5 +1418,13 @@ internal void ClearDirtyComponentsDirtyBits()
}
}
}
+
+ void ResetSyncObjects()
+ {
+ foreach (NetworkBehaviour comp in NetworkBehaviours)
+ {
+ comp.ResetSyncObjects();
+ }
+ }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkIdentity.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkIdentity.cs.meta
index 85a8007..7b96521 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkIdentity.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkIdentity.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManager.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManager.cs
index 6d54ffb..78bd5e6 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManager.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManager.cs
@@ -12,22 +12,27 @@ namespace Mirror
///
/// Enumeration of methods of where to spawn player objects in multiplayer games.
///
- public enum PlayerSpawnMethod
- {
- Random,
- RoundRobin
- }
+ public enum PlayerSpawnMethod { Random, RoundRobin }
+
+ ///
+ /// Enumeration of methods of current Network Manager state at runtime.
+ ///
+ public enum NetworkManagerMode { Offline, ServerOnly, ClientOnly, Host }
+ [DisallowMultipleComponent]
[AddComponentMenu("Network/NetworkManager")]
[HelpURL("https://mirror-networking.com/docs/Components/NetworkManager.html")]
public class NetworkManager : MonoBehaviour
{
+ static readonly ILogger logger = LogFactory.GetLogger();
+
///
/// A flag to control whether the NetworkManager object is destroyed when the scene changes.
/// This should be set if your game has a single NetworkManager that exists for the lifetime of the process. If there is a NetworkManager in each scene, then this should not be set.
///
[Header("Configuration")]
[FormerlySerializedAs("m_DontDestroyOnLoad")]
+ [Tooltip("Should the Network Manager object be persisted through scene changes?")]
public bool dontDestroyOnLoad = true;
///
@@ -35,32 +40,37 @@ public class NetworkManager : MonoBehaviour
/// This is required when multiple instances of a program using networking are running on the same machine, such as when testing using localhost. But this is not recommended when deploying to mobile platforms.
///
[FormerlySerializedAs("m_RunInBackground")]
+ [Tooltip("Should the server or client keep running in the background?")]
public bool runInBackground = true;
///
/// Automatically invoke StartServer()
/// If the application is a Server Build or run with the -batchMode command line arguement, StartServer is automatically invoked.
///
+ [Tooltip("Should the server auto-start when the game is started in a headless build?")]
public bool startOnHeadless = true;
- ///
- /// Server Update frequency, per second. Use around 60Hz for fast paced games like Counter-Strike to minimize latency. Use around 30Hz for games like WoW to minimize computations. Use around 1-10Hz for slow paced games like EVE.
- ///
- [Tooltip("Server Update frequency, per second. Use around 60Hz for fast paced games like Counter-Strike to minimize latency. Use around 30Hz for games like WoW to minimize computations. Use around 1-10Hz for slow paced games like EVE.")]
- public int serverTickRate = 30;
-
///
/// Enables verbose debug messages in the console
///
[FormerlySerializedAs("m_ShowDebugMessages")]
+ [Tooltip("This will enable verbose debug messages in the Unity Editor console")]
public bool showDebugMessages;
+ ///
+ /// Server Update frequency, per second. Use around 60Hz for fast paced games like Counter-Strike to minimize latency. Use around 30Hz for games like WoW to minimize computations. Use around 1-10Hz for slow paced games like EVE.
+ ///
+ [Tooltip("Server Update frequency, per second. Use around 60Hz for fast paced games like Counter-Strike to minimize latency. Use around 30Hz for games like WoW to minimize computations. Use around 1-10Hz for slow paced games like EVE.")]
+ public int serverTickRate = 30;
+
///
/// The scene to switch to when offline.
/// Setting this makes the NetworkManager do scene management. This scene will be switched to when a network session is completed - such as a client disconnect, or a server shutdown.
///
+ [Header("Scene Management")]
[Scene]
[FormerlySerializedAs("m_OfflineScene")]
+ [Tooltip("Scene that Mirror will switch to when the client or server is stopped")]
public string offlineScene = "";
///
@@ -69,11 +79,12 @@ public class NetworkManager : MonoBehaviour
///
[Scene]
[FormerlySerializedAs("m_OnlineScene")]
+ [Tooltip("Scene that Mirror will switch to when the server is started. Clients will recieve a Scene Message to load the server's current scene when they connect.")]
public string onlineScene = "";
- [Header("Network Info")]
-
// transport layer
+ [Header("Network Info")]
+ [Tooltip("Transport component attached to this object that server and client will use to connect")]
[SerializeField]
protected Transport transport;
@@ -82,6 +93,7 @@ public class NetworkManager : MonoBehaviour
/// For clients, this is the address of the server that is connected to. For servers, this is the local address.
///
[FormerlySerializedAs("m_NetworkAddress")]
+ [Tooltip("Network Address where the client should connect to the server. Server does not use this for anything.")]
public string networkAddress = "localhost";
///
@@ -89,41 +101,56 @@ public class NetworkManager : MonoBehaviour
/// This effects the memory usage of the network layer.
///
[FormerlySerializedAs("m_MaxConnections")]
+ [Tooltip("Maximum number of concurrent connections.")]
public int maxConnections = 4;
+ // This value is passed to NetworkServer in SetupServer
///
- /// Number of active player objects across all connections on the server.
- /// This is only valid on the host / server.
+ /// Should the server disconnect remote connections that have gone silent for more than Server Idle Timeout?
///
- public int numPlayers => NetworkServer.connections.Count(kv => kv.Value.identity != null);
+ [Tooltip("Server Only - Disconnects remote connections that have been silent for more than Server Idle Timeout")]
+ public bool disconnectInactiveConnections;
- [Header("Authentication")]
+ // This value is passed to NetworkServer in SetupServer
+ ///
+ /// Timeout in seconds since last message from a client after which server will auto-disconnect.
+ /// By default, clients send at least a Ping message every 2 seconds.
+ /// The Host client is immune from idle timeout disconnection.
+ /// Default value is 60 seconds.
+ ///
+ [Tooltip("Timeout in seconds since last message from a client after which server will auto-disconnect if Disconnect Inactive Connections is enabled.")]
+ public float disconnectInactiveTimeout = 60f;
+ [Header("Authentication")]
+ [Tooltip("Authentication component attached to this object")]
public NetworkAuthenticator authenticator;
///
/// The default prefab to be used to create player objects on the server.
/// Player objects are created in the default handler for AddPlayer() on the server. Implementing OnServerAddPlayer overrides this behaviour.
///
- [Header("Spawn Info")]
+ [Header("Player Object")]
[FormerlySerializedAs("m_PlayerPrefab")]
+ [Tooltip("Prefab of the player object. Prefab must have a Network Identity component. May be an empty game object or a full avatar.")]
public GameObject playerPrefab;
///
/// A flag to control whether or not player objects are automatically created on connect, and on scene change.
///
[FormerlySerializedAs("m_AutoCreatePlayer")]
+ [Tooltip("Should Mirror automatically spawn the player after scene change?")]
public bool autoCreatePlayer = true;
///
/// The current method of spawning players used by the NetworkManager.
///
[FormerlySerializedAs("m_PlayerSpawnMethod")]
+ [Tooltip("Round Robin or Random order of Start Position selection")]
public PlayerSpawnMethod playerSpawnMethod;
///
/// List of prefabs that will be registered with the spawning system.
- /// For each of these prefabs, ClientManager.RegisterPrefab() will be automatically invoke.
+ /// For each of these prefabs, ClientScene.RegisterPrefab() will be automatically invoked.
///
[FormerlySerializedAs("m_SpawnPrefabs"), HideInInspector]
public List spawnPrefabs = new List();
@@ -131,7 +158,13 @@ public class NetworkManager : MonoBehaviour
///
/// NetworkManager singleton
///
- public static NetworkManager singleton;
+ public static NetworkManager singleton { get; private set; }
+
+ ///
+ /// Number of active player objects across all connections on the server.
+ /// This is only valid on the host / server.
+ ///
+ public int numPlayers => NetworkServer.connections.Count(kv => kv.Value.identity != null);
///
/// True if the server or client is started and running
@@ -149,38 +182,18 @@ public class NetworkManager : MonoBehaviour
[NonSerialized]
public bool clientLoadedScene;
- ///
- /// Obsolete: Use instead
- ///
- /// Returns True if NetworkClient.isConnected
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use NetworkClient.isConnected instead")]
- public bool IsClientConnected()
- {
- return NetworkClient.isConnected;
- }
-
- ///
- /// Obsolete: Use instead.
- /// This is a static property now. This method will be removed by summer 2019.
- ///
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use isHeadless instead of IsHeadless()")]
- public static bool IsHeadless()
- {
- return isHeadless;
- }
-
///
/// headless mode detection
///
public static bool isHeadless => SystemInfo.graphicsDeviceType == GraphicsDeviceType.Null;
- ///
- /// Obsolete: Use directly
- /// For example, use NetworkClient.Send(message) instead of NetworkManager.client.Send(message)
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use NetworkClient directly, it will be made static soon. For example, use NetworkClient.Send(message) instead of NetworkManager.client.Send(message)")]
- public NetworkClient client => NetworkClient.singleton;
+ // helper enum to know if we started the networkmanager as server/client/host.
+ // -> this is necessary because when StartHost changes server scene to
+ // online scene, FinishLoadScene is called and the host client isn't
+ // connected yet (no need to connect it before server was fully set up).
+ // in other words, we need this to know which mode we are running in
+ // during FinishLoadScene.
+ public NetworkManagerMode mode { get; private set; }
#region Unity Callbacks
@@ -197,18 +210,19 @@ public virtual void OnValidate()
if (transport == null)
{
transport = gameObject.AddComponent();
- Debug.Log("NetworkManager: added default Transport because there was none yet.");
+ logger.Log("NetworkManager: added default Transport because there was none yet.");
}
#if UNITY_EDITOR
UnityEditor.Undo.RecordObject(gameObject, "Added default Transport");
#endif
}
- maxConnections = Mathf.Max(maxConnections, 0); // always >= 0
+ // always >= 0
+ maxConnections = Mathf.Max(maxConnections, 0);
if (playerPrefab != null && playerPrefab.GetComponent() == null)
{
- Debug.LogError("NetworkManager - playerPrefab must have a NetworkIdentity.");
+ logger.LogError("NetworkManager - playerPrefab must have a NetworkIdentity.");
playerPrefab = null;
}
}
@@ -218,14 +232,15 @@ public virtual void OnValidate()
///
public virtual void Awake()
{
- Debug.Log("Thank you for using Mirror! https://mirror-networking.com");
+ // Don't allow collision-destroyed second instance to continue.
+ if (!InitializeSingleton()) return;
+
+ logger.Log("Thank you for using Mirror! https://mirror-networking.com");
// Set the networkSceneName to prevent a scene reload
// if client connection to server fails.
networkSceneName = offlineScene;
- InitializeSingleton();
-
// setup OnSceneLoaded callback
SceneManager.sceneLoaded += OnSceneLoaded;
}
@@ -265,13 +280,23 @@ public virtual void LateUpdate()
#region Start & Stop
- ///
- /// This starts a new server.
- /// This uses the networkPort property as the listen port.
- ///
- ///
- public bool StartServer()
+ // keep the online scene change check in a separate function
+ bool IsServerOnlineSceneChangeNeeded()
+ {
+ // Only change scene if the requested online scene is not blank, and is not already loaded
+ return !string.IsNullOrEmpty(onlineScene) && !IsSceneActive(onlineScene) && onlineScene != offlineScene;
+ }
+
+ public static bool IsSceneActive(string scene)
+ {
+ Scene activeScene = SceneManager.GetActiveScene();
+ return activeScene.path == scene || activeScene.name == scene;
+ }
+
+ // full server setup code, without spawning objects yet
+ void SetupServer()
{
+ if (logger.LogEnabled()) logger.Log("NetworkManager SetupServer");
InitializeSingleton();
if (runInBackground)
@@ -285,11 +310,12 @@ public bool StartServer()
ConfigureServerFrameRate();
- if (!NetworkServer.Listen(maxConnections))
- {
- Debug.LogError("StartServer listen failed.");
- return false;
- }
+ // Copy auto-disconnect settings to NetworkServer
+ NetworkServer.disconnectInactiveTimeout = disconnectInactiveTimeout;
+ NetworkServer.disconnectInactiveConnections = disconnectInactiveConnections;
+
+ // start listening to network connections
+ NetworkServer.Listen(maxConnections);
// call OnStartServer AFTER Listen, so that NetworkServer.active is
// true and we can call NetworkServer.Spawn in OnStartServer
@@ -304,28 +330,54 @@ public bool StartServer()
// this must be after Listen(), since that registers the default message handlers
RegisterServerMessages();
- if (LogFilter.Debug) Debug.Log("NetworkManager StartServer");
isNetworkActive = true;
+ }
- // Only change scene if the requested online scene is not blank, and is not already loaded
- string loadedSceneName = SceneManager.GetActiveScene().name;
- if (!string.IsNullOrEmpty(onlineScene) && onlineScene != loadedSceneName && onlineScene != offlineScene)
+ ///
+ /// This starts a new server.
+ ///
+ public void StartServer()
+ {
+ mode = NetworkManagerMode.ServerOnly;
+
+ // StartServer is inherently ASYNCHRONOUS (=doesn't finish immediately)
+ //
+ // Here is what it does:
+ // Listen
+ // if onlineScene:
+ // LoadSceneAsync
+ // ...
+ // FinishLoadSceneServerOnly
+ // SpawnObjects
+ // else:
+ // SpawnObjects
+ //
+ // there is NO WAY to make it synchronous because both LoadSceneAsync
+ // and LoadScene do not finish loading immediately. as long as we
+ // have the onlineScene feature, it will be asynchronous!
+
+ SetupServer();
+
+ // scene change needed? then change scene and spawn afterwards.
+ if (IsServerOnlineSceneChangeNeeded())
{
ServerChangeScene(onlineScene);
}
+ // otherwise spawn directly
else
{
NetworkServer.SpawnObjects();
}
- return true;
}
///
- /// This starts a network client. It uses the networkAddress and networkPort properties as the address to connect to.
+ /// This starts a network client. It uses the networkAddress property as the address to connect to.
/// This makes the newly created client connect to the server immediately.
///
public void StartClient()
{
+ mode = NetworkManagerMode.ClientOnly;
+
InitializeSingleton();
if (authenticator != null)
@@ -343,30 +395,175 @@ public void StartClient()
if (string.IsNullOrEmpty(networkAddress))
{
- Debug.LogError("Must set the Network Address field in the manager");
+ logger.LogError("Must set the Network Address field in the manager");
return;
}
- if (LogFilter.Debug) Debug.Log("NetworkManager StartClient address:" + networkAddress);
+ if (logger.LogEnabled()) logger.Log("NetworkManager StartClient address:" + networkAddress);
NetworkClient.Connect(networkAddress);
OnStartClient();
}
+ ///
+ /// This starts a network client. It uses the Uri parameter as the address to connect to.
+ /// This makes the newly created client connect to the server immediately.
+ ///
+ /// location of the server to connect to
+ public void StartClient(Uri uri)
+ {
+ mode = NetworkManagerMode.ClientOnly;
+
+ InitializeSingleton();
+
+ if (authenticator != null)
+ {
+ authenticator.OnStartClient();
+ authenticator.OnClientAuthenticated.AddListener(OnClientAuthenticated);
+ }
+
+ if (runInBackground)
+ {
+ Application.runInBackground = true;
+ }
+
+ isNetworkActive = true;
+
+ RegisterClientMessages();
+
+ if (logger.LogEnabled()) logger.Log("NetworkManager StartClient address:" + uri);
+ networkAddress = uri.Host;
+
+ NetworkClient.Connect(uri);
+
+ OnStartClient();
+ }
+
///
/// This starts a network "host" - a server and client in the same application.
/// The client returned from StartHost() is a special "local" client that communicates to the in-process server using a message queue instead of the real network. But in almost all other cases, it can be treated as a normal client.
///
- public virtual void StartHost()
+ public void StartHost()
{
+ mode = NetworkManagerMode.Host;
+
+ // StartHost is inherently ASYNCHRONOUS (=doesn't finish immediately)
+ //
+ // Here is what it does:
+ // Listen
+ // ConnectHost
+ // if onlineScene:
+ // LoadSceneAsync
+ // ...
+ // FinishLoadSceneHost
+ // FinishStartHost
+ // SpawnObjects
+ // StartHostClient <= not guaranteed to happen after SpawnObjects if onlineScene is set!
+ // ClientAuth
+ // success: server sends changescene msg to client
+ // else:
+ // FinishStartHost
+ //
+ // there is NO WAY to make it synchronous because both LoadSceneAsync
+ // and LoadScene do not finish loading immediately. as long as we
+ // have the onlineScene feature, it will be asynchronous!
+
+ // setup server first
+ SetupServer();
+
+ // call OnStartHost AFTER SetupServer. this way we can use
+ // NetworkServer.Spawn etc. in there too. just like OnStartServer
+ // is called after the server is actually properly started.
OnStartHost();
- if (StartServer())
+
+ // scene change needed? then change scene and spawn afterwards.
+ // => BEFORE host client connects. if client auth succeeds then the
+ // server tells it to load 'onlineScene'. we can't do that if
+ // server is still in 'offlineScene'. so load on server first.
+ if (IsServerOnlineSceneChangeNeeded())
+ {
+ // call FinishStartHost after changing scene.
+ finishStartHostPending = true;
+ ServerChangeScene(onlineScene);
+ }
+ // otherwise call FinishStartHost directly
+ else
{
- ConnectLocalClient();
- OnStartClient();
+ FinishStartHost();
}
}
+ // This may be set true in StartHost and is evaluated in FinishStartHost
+ bool finishStartHostPending;
+
+ // FinishStartHost is guaranteed to be called after the host server was
+ // fully started and all the asynchronous StartHost magic is finished
+ // (= scene loading), or immediately if there was no asynchronous magic.
+ //
+ // note: we don't really need FinishStartClient/FinishStartServer. the
+ // host version is enough.
+ void FinishStartHost()
+ {
+ // ConnectHost needs to be called BEFORE SpawnObjects:
+ // https://github.com/vis2k/Mirror/pull/1249/
+ // -> this sets NetworkServer.localConnection.
+ // -> localConnection needs to be set before SpawnObjects because:
+ // -> SpawnObjects calls OnStartServer in all NetworkBehaviours
+ // -> OnStartServer might spawn an object and set [SyncVar(hook="OnColorChanged")] object.color = green;
+ // -> this calls SyncVar.set (generated by Weaver), which has
+ // a custom case for host mode (because host mode doesn't
+ // get OnDeserialize calls, where SyncVar hooks are usually
+ // called):
+ //
+ // if (!SyncVarEqual(value, ref color))
+ // {
+ // if (NetworkServer.localClientActive && !getSyncVarHookGuard(1uL))
+ // {
+ // setSyncVarHookGuard(1uL, value: true);
+ // OnColorChangedHook(value);
+ // setSyncVarHookGuard(1uL, value: false);
+ // }
+ // SetSyncVar(value, ref color, 1uL);
+ // }
+ //
+ // -> localClientActive needs to be true, otherwise the hook
+ // isn't called in host mode!
+ //
+ // TODO call this after spawnobjects and worry about the syncvar hook fix later?
+ NetworkClient.ConnectHost();
+
+ // server scene was loaded. now spawn all the objects
+ NetworkServer.SpawnObjects();
+
+ // connect client and call OnStartClient AFTER server scene was
+ // loaded and all objects were spawned.
+ // DO NOT do this earlier. it would cause race conditions where a
+ // client will do things before the server is even fully started.
+ logger.Log("StartHostClient called");
+ StartHostClient();
+ }
+
+ void StartHostClient()
+ {
+ logger.Log("NetworkManager ConnectLocalClient");
+
+ if (authenticator != null)
+ {
+ authenticator.OnStartClient();
+ authenticator.OnClientAuthenticated.AddListener(OnClientAuthenticated);
+ }
+
+ networkAddress = "localhost";
+ NetworkServer.ActivateHostScene();
+ RegisterClientMessages();
+
+ // ConnectLocalServer needs to be called AFTER RegisterClientMessages
+ // (https://github.com/vis2k/Mirror/pull/1249/)
+ NetworkClient.ConnectLocalServer();
+
+ OnStartClient();
+ }
+
///
/// This stops both the client and the server that the manager is using.
///
@@ -374,8 +571,16 @@ public void StopHost()
{
OnStopHost();
- StopServer();
+ // TODO try to move DisconnectLocalServer into StopClient(), and
+ // then call StopClient() before StopServer(). needs testing!.
+
+ // DisconnectLocalServer needs to be called so that the host client
+ // receives a DisconnectMessage too.
+ // fixes: https://github.com/vis2k/Mirror/issues/1515
+ NetworkClient.DisconnectLocalServer();
+
StopClient();
+ StopServer();
}
///
@@ -391,16 +596,22 @@ public void StopServer()
OnStopServer();
- if (LogFilter.Debug) Debug.Log("NetworkManager StopServer");
+ logger.Log("NetworkManager StopServer");
isNetworkActive = false;
NetworkServer.Shutdown();
+
+ // set offline mode BEFORE changing scene so that FinishStartScene
+ // doesn't think we need initialize anything.
+ mode = NetworkManagerMode.Offline;
+
if (!string.IsNullOrEmpty(offlineScene))
{
ServerChangeScene(offlineScene);
}
- CleanupNetworkIdentities();
startPositionIndex = 0;
+
+ networkSceneName = "";
}
///
@@ -413,19 +624,26 @@ public void StopClient()
OnStopClient();
- if (LogFilter.Debug) Debug.Log("NetworkManager StopClient");
+ logger.Log("NetworkManager StopClient");
isNetworkActive = false;
// shutdown client
NetworkClient.Disconnect();
NetworkClient.Shutdown();
- if (!string.IsNullOrEmpty(offlineScene) && SceneManager.GetActiveScene().name != offlineScene)
+ // set offline mode BEFORE changing scene so that FinishStartScene
+ // doesn't think we need initialize anything.
+ mode = NetworkManagerMode.Offline;
+
+ // If this is the host player, StopServer will already be changing scenes.
+ // Check loadingSceneAsync to ensure we don't double-invoke the scene change.
+ // Check if NetworkServer.active because we can get here via Disconnect before server has started to change scenes.
+ if (!string.IsNullOrEmpty(offlineScene) && !IsSceneActive(offlineScene) && loadingSceneAsync == null && !NetworkServer.active)
{
ClientChangeScene(offlineScene, SceneOperation.Normal);
}
- CleanupNetworkIdentities();
+ networkSceneName = "";
}
///
@@ -449,12 +667,6 @@ public virtual void OnApplicationQuit()
StopServer();
print("OnApplicationQuit: stopped server");
}
-
- // stop transport (e.g. to shut down threads)
- // (when pressing Stop in the Editor, Unity keeps threads alive
- // until we press Start again. so if Transports use threads, we
- // really want them to end now and not after next start)
- Transport.activeTransport.Shutdown();
}
///
@@ -470,68 +682,58 @@ public virtual void ConfigureServerFrameRate()
if (!NetworkClient.active && isHeadless)
{
Application.targetFrameRate = serverTickRate;
- Debug.Log("Server Tick Rate set to: " + Application.targetFrameRate + " Hz.");
+ if (logger.logEnabled) logger.Log("Server Tick Rate set to: " + Application.targetFrameRate + " Hz.");
}
#endif
}
- void InitializeSingleton()
+ bool InitializeSingleton()
{
- if (singleton != null && singleton == this)
- {
- return;
- }
+ if (singleton != null && singleton == this) return true;
// do this early
LogFilter.Debug = showDebugMessages;
+ if (LogFilter.Debug)
+ {
+ LogFactory.EnableDebugMode();
+ }
if (dontDestroyOnLoad)
{
if (singleton != null)
{
- Debug.LogWarning("Multiple NetworkManagers detected in the scene. Only one NetworkManager can exist at a time. The duplicate NetworkManager will be destroyed.");
+ logger.LogWarning("Multiple NetworkManagers detected in the scene. Only one NetworkManager can exist at a time. The duplicate NetworkManager will be destroyed.");
Destroy(gameObject);
- return;
+
+ // Return false to not allow collision-destroyed second instance to continue.
+ return false;
}
- if (LogFilter.Debug) Debug.Log("NetworkManager created singleton (DontDestroyOnLoad)");
+ logger.Log("NetworkManager created singleton (DontDestroyOnLoad)");
singleton = this;
if (Application.isPlaying) DontDestroyOnLoad(gameObject);
}
else
{
- if (LogFilter.Debug) Debug.Log("NetworkManager created singleton (ForScene)");
+ logger.Log("NetworkManager created singleton (ForScene)");
singleton = this;
}
// set active transport AFTER setting singleton.
// so only if we didn't destroy ourselves.
Transport.activeTransport = transport;
+
+ return true;
}
void RegisterServerMessages()
{
NetworkServer.RegisterHandler(OnServerConnectInternal, false);
NetworkServer.RegisterHandler(OnServerDisconnectInternal, false);
- NetworkServer.RegisterHandler(OnServerReadyMessageInternal);
NetworkServer.RegisterHandler(OnServerAddPlayerInternal);
- NetworkServer.RegisterHandler(OnServerRemovePlayerMessageInternal);
NetworkServer.RegisterHandler(OnServerErrorInternal, false);
- }
-
- void ConnectLocalClient()
- {
- if (LogFilter.Debug) Debug.Log("NetworkManager StartHost");
-
- if (authenticator != null)
- {
- authenticator.OnStartClient();
- authenticator.OnClientAuthenticated.AddListener(OnClientAuthenticated);
- }
- networkAddress = "localhost";
- NetworkServer.ActivateLocalClientScene();
- NetworkClient.ConnectLocalServer();
- RegisterClientMessages();
+ // Network Server initially registers its own handler for this, so we replace it here.
+ NetworkServer.ReplaceHandler(OnServerReadyMessageInternal);
}
void RegisterClientMessages()
@@ -556,14 +758,6 @@ void RegisterClientMessages()
}
}
- void CleanupNetworkIdentities()
- {
- foreach (NetworkIdentity identity in Resources.FindObjectsOfTypeAll())
- {
- identity.MarkForReset();
- }
- }
-
///
/// This is the only way to clear the singleton, so another instance can be created.
///
@@ -585,7 +779,7 @@ public static void Shutdown()
///
public virtual void OnDestroy()
{
- if (LogFilter.Debug) Debug.Log("NetworkManager destroyed");
+ logger.Log("NetworkManager destroyed");
}
#endregion
@@ -596,13 +790,13 @@ public virtual void OnDestroy()
/// The name of the current network scene.
///
///
- /// This is populated if the NetworkManager is doing scene management. This should not be changed directly. Calls to ServerChangeScene() cause this to change. New clients that connect to a server will automatically load this scene.
+ /// This is populated if the NetworkManager is doing scene management. Calls to ServerChangeScene() cause this to change. New clients that connect to a server will automatically load this scene.
/// This is used to make sure that all scene changes are initialized by Mirror.
/// Loading a scene manually wont set networkSceneName, so Mirror would still load it again on start.
///
- public static string networkSceneName = "";
+ public static string networkSceneName { get; protected set; } = "";
- static UnityEngine.AsyncOperation loadingSceneAsync;
+ public static UnityEngine.AsyncOperation loadingSceneAsync;
///
/// This causes the server to switch scenes and sets the networkSceneName.
@@ -610,63 +804,71 @@ public virtual void OnDestroy()
///
///
public virtual void ServerChangeScene(string newSceneName)
- {
- ServerChangeScene(newSceneName, LoadSceneMode.Single, LocalPhysicsMode.None);
- }
-
- ///
- /// This causes the server to switch scenes and sets the networkSceneName.
- /// Clients that connect to this server will automatically switch to this scene. This is called autmatically if onlineScene or offlineScene are set, but it can be called from user code to switch scenes again while the game is in progress. This automatically sets clients to be not-ready. The clients must call NetworkClient.Ready() again to participate in the new scene.
- ///
- ///
- ///
- ///
- public virtual void ServerChangeScene(string newSceneName, LoadSceneMode sceneMode, LocalPhysicsMode physicsMode)
{
if (string.IsNullOrEmpty(newSceneName))
{
- Debug.LogError("ServerChangeScene empty scene name");
+ logger.LogError("ServerChangeScene empty scene name");
return;
}
- if (LogFilter.Debug) Debug.Log("ServerChangeScene " + newSceneName);
+ if (logger.logEnabled) logger.Log("ServerChangeScene " + newSceneName);
NetworkServer.SetAllClientsNotReady();
networkSceneName = newSceneName;
// Let server prepare for scene change
OnServerChangeScene(newSceneName);
+ // Suspend the server's transport while changing scenes
+ // It will be re-enabled in FinishScene.
+ Transport.activeTransport.enabled = false;
+
loadingSceneAsync = SceneManager.LoadSceneAsync(newSceneName);
- SceneMessage msg = new SceneMessage()
+ // ServerChangeScene can be called when stopping the server
+ // when this happens the server is not active so does not need to tell clients about the change
+ if (NetworkServer.active)
{
- sceneName = newSceneName,
- };
-
- NetworkServer.SendToAll(msg);
+ // notify all clients about the new scene
+ NetworkServer.SendToAll(new SceneMessage { sceneName = newSceneName });
+ }
startPositionIndex = 0;
startPositions.Clear();
}
- internal void ClientChangeScene(string newSceneName, SceneOperation sceneOperation = SceneOperation.Normal)
+ // This is only set in ClientChangeScene below...never on server.
+ // We need to check this in OnClientSceneChanged called from FinishLoadSceneClientOnly
+ // to prevent AddPlayer message after loading/unloading additive scenes
+ SceneOperation clientSceneOperation = SceneOperation.Normal;
+
+ internal void ClientChangeScene(string newSceneName, SceneOperation sceneOperation = SceneOperation.Normal, bool customHandling = false)
{
if (string.IsNullOrEmpty(newSceneName))
{
- Debug.LogError("ClientChangeScene empty scene name");
+ logger.LogError("ClientChangeScene empty scene name");
return;
}
- if (LogFilter.Debug) Debug.Log("ClientChangeScene newSceneName:" + newSceneName + " networkSceneName:" + networkSceneName);
+ if (logger.LogEnabled()) logger.Log("ClientChangeScene newSceneName:" + newSceneName + " networkSceneName:" + networkSceneName);
// vis2k: pause message handling while loading scene. otherwise we will process messages and then lose all
// the state as soon as the load is finishing, causing all kinds of bugs because of missing state.
// (client may be null after StopClient etc.)
- if (LogFilter.Debug) Debug.Log("ClientChangeScene: pausing handlers while scene is loading to avoid data loss after scene was loaded.");
+ if (logger.LogEnabled()) logger.Log("ClientChangeScene: pausing handlers while scene is loading to avoid data loss after scene was loaded.");
Transport.activeTransport.enabled = false;
// Let client prepare for scene change
- OnClientChangeScene(newSceneName, sceneOperation);
+ OnClientChangeScene(newSceneName, sceneOperation, customHandling);
+
+ // scene handling will happen in overrides of OnClientChangeScene and/or OnClientSceneChanged
+ if (customHandling)
+ {
+ FinishLoadScene();
+ return;
+ }
+
+ // cache sceneOperation so we know what was done in OnClientSceneChanged called from FinishLoadSceneClientOnly
+ clientSceneOperation = sceneOperation;
switch (sceneOperation)
{
@@ -674,19 +876,30 @@ internal void ClientChangeScene(string newSceneName, SceneOperation sceneOperati
loadingSceneAsync = SceneManager.LoadSceneAsync(newSceneName);
break;
case SceneOperation.LoadAdditive:
- if (!SceneManager.GetSceneByName(newSceneName).IsValid())
+ // Ensure additive scene is not already loaded on client by name or path
+ // since we don't know which was passed in the Scene message
+ if (!SceneManager.GetSceneByName(newSceneName).IsValid() && !SceneManager.GetSceneByPath(newSceneName).IsValid())
loadingSceneAsync = SceneManager.LoadSceneAsync(newSceneName, LoadSceneMode.Additive);
else
- Debug.LogWarningFormat("Scene {0} is already loaded", newSceneName);
+ {
+ logger.LogWarning($"Scene {newSceneName} is already loaded");
+
+ // Re-enable the transport that we disabled before entering this switch
+ Transport.activeTransport.enabled = true;
+ }
break;
case SceneOperation.UnloadAdditive:
- if (SceneManager.GetSceneByName(newSceneName).IsValid())
+ // Ensure additive scene is actually loaded on client by name or path
+ // since we don't know which was passed in the Scene message
+ if (SceneManager.GetSceneByName(newSceneName).IsValid() || SceneManager.GetSceneByPath(newSceneName).IsValid())
+ loadingSceneAsync = SceneManager.UnloadSceneAsync(newSceneName, UnloadSceneOptions.UnloadAllEmbeddedSceneObjects);
+ else
{
- if (SceneManager.GetSceneByName(newSceneName) != null)
- loadingSceneAsync = SceneManager.UnloadSceneAsync(newSceneName, UnloadSceneOptions.UnloadAllEmbeddedSceneObjects);
+ logger.LogWarning($"Cannot unload {newSceneName} with UnloadAdditive operation");
+
+ // Re-enable the transport that we disabled before entering this switch
+ Transport.activeTransport.enabled = true;
}
- else
- Debug.LogWarning("Cannot unload the active scene with UnloadAdditive operation");
break;
}
@@ -712,12 +925,12 @@ void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
// TODO only respawn the server objects from that scene later!
NetworkServer.SpawnObjects();
- Debug.Log("Respawned Server objects after additive scene load: " + scene.name);
+ if (logger.LogEnabled()) logger.Log("Respawned Server objects after additive scene load: " + scene.name);
}
if (NetworkClient.active)
{
ClientScene.PrepareToSpawnSceneObjects();
- Debug.Log("Rebuild Client spawnableObjects after additive scene load: " + scene.name);
+ if (logger.LogEnabled()) logger.Log("Rebuild Client spawnableObjects after additive scene load: " + scene.name);
}
}
}
@@ -726,7 +939,7 @@ static void UpdateScene()
{
if (singleton != null && loadingSceneAsync != null && loadingSceneAsync.isDone)
{
- if (LogFilter.Debug) Debug.Log("ClientChangeScene done readyCon:" + clientReadyConnection);
+ if (logger.LogEnabled()) logger.Log("ClientChangeScene done readyCon:" + clientReadyConnection);
singleton.FinishLoadScene();
loadingSceneAsync.allowSceneActivation = true;
loadingSceneAsync = null;
@@ -738,25 +951,109 @@ void FinishLoadScene()
// NOTE: this cannot use NetworkClient.allClients[0] - that client may be for a completely different purpose.
// process queued messages that we received while loading the scene
- if (LogFilter.Debug) Debug.Log("FinishLoadScene: resuming handlers after scene was loading.");
+ logger.Log("FinishLoadScene: resuming handlers after scene was loading.");
Transport.activeTransport.enabled = true;
+ // host mode?
+ if (mode == NetworkManagerMode.Host)
+ {
+ FinishLoadSceneHost();
+ }
+ // server-only mode?
+ else if (mode == NetworkManagerMode.ServerOnly)
+ {
+ FinishLoadSceneServerOnly();
+ }
+ // client-only mode?
+ else if (mode == NetworkManagerMode.ClientOnly)
+ {
+ FinishLoadSceneClientOnly();
+ }
+ // otherwise we called it after stopping when loading offline scene.
+ // do nothing then.
+ }
+
+ // finish load scene part for host mode. makes code easier and is
+ // necessary for FinishStartHost later.
+ // (the 3 things have to happen in that exact order)
+ void FinishLoadSceneHost()
+ {
+ // debug message is very important. if we ever break anything then
+ // it's very obvious to notice.
+ logger.Log("Finished loading scene in host mode.");
+
if (clientReadyConnection != null)
{
- clientLoadedScene = true;
OnClientConnect(clientReadyConnection);
+ clientLoadedScene = true;
clientReadyConnection = null;
}
- if (NetworkServer.active)
+ // do we need to finish a StartHost() call?
+ // then call FinishStartHost and let it take care of spawning etc.
+ if (finishStartHostPending)
+ {
+ finishStartHostPending = false;
+ FinishStartHost();
+
+ // call OnServerSceneChanged
+ OnServerSceneChanged(networkSceneName);
+
+ // DO NOT call OnClientSceneChanged here.
+ // the scene change happened because StartHost loaded the
+ // server's online scene. it has nothing to do with the client.
+ // this was not meant as a client scene load, so don't call it.
+ //
+ // otherwise AddPlayer would be called twice:
+ // -> once for client OnConnected
+ // -> once in OnClientSceneChanged
+ }
+ // otherwise we just changed a scene in host mode
+ else
{
+ // spawn server objects
NetworkServer.SpawnObjects();
+
+ // call OnServerSceneChanged
OnServerSceneChanged(networkSceneName);
+
+ if (NetworkClient.isConnected)
+ {
+ // let client know that we changed scene
+ OnClientSceneChanged(NetworkClient.connection);
+ }
+ }
+ }
+
+ // finish load scene part for server-only. . makes code easier and is
+ // necessary for FinishStartServer later.
+ void FinishLoadSceneServerOnly()
+ {
+ // debug message is very important. if we ever break anything then
+ // it's very obvious to notice.
+ logger.Log("Finished loading scene in server-only mode.");
+
+ NetworkServer.SpawnObjects();
+ OnServerSceneChanged(networkSceneName);
+ }
+
+ // finish load scene part for client-only. makes code easier and is
+ // necessary for FinishStartClient later.
+ void FinishLoadSceneClientOnly()
+ {
+ // debug message is very important. if we ever break anything then
+ // it's very obvious to notice.
+ logger.Log("Finished loading scene in client-only mode.");
+
+ if (clientReadyConnection != null)
+ {
+ OnClientConnect(clientReadyConnection);
+ clientLoadedScene = true;
+ clientReadyConnection = null;
}
if (NetworkClient.isConnected)
{
- RegisterClientMessages();
OnClientSceneChanged(NetworkClient.connection);
}
}
@@ -765,7 +1062,7 @@ void FinishLoadScene()
#region Start Positions
- static int startPositionIndex;
+ public static int startPositionIndex;
///
/// List of transforms populted by NetworkStartPosition components found in the scene.
@@ -779,7 +1076,7 @@ void FinishLoadScene()
/// Transform to register.
public static void RegisterStartPosition(Transform start)
{
- if (LogFilter.Debug) Debug.Log("RegisterStartPosition: (" + start.gameObject.name + ") " + start.position);
+ if (logger.LogEnabled()) logger.Log("RegisterStartPosition: (" + start.gameObject.name + ") " + start.position);
startPositions.Add(start);
// reorder the list so that round-robin spawning uses the start positions
@@ -796,17 +1093,42 @@ public static void RegisterStartPosition(Transform start)
/// Transform to unregister.
public static void UnRegisterStartPosition(Transform start)
{
- if (LogFilter.Debug) Debug.Log("UnRegisterStartPosition: (" + start.gameObject.name + ") " + start.position);
+ if (logger.LogEnabled()) logger.Log("UnRegisterStartPosition: (" + start.gameObject.name + ") " + start.position);
startPositions.Remove(start);
}
+ ///
+ /// This finds a spawn position based on NetworkStartPosition objects in the scene.
+ /// This is used by the default implementation of OnServerAddPlayer.
+ ///
+ /// Returns the transform to spawn a player at, or null.
+ public Transform GetStartPosition()
+ {
+ // first remove any dead transforms
+ startPositions.RemoveAll(t => t == null);
+
+ if (startPositions.Count == 0)
+ return null;
+
+ if (playerSpawnMethod == PlayerSpawnMethod.Random)
+ {
+ return startPositions[UnityEngine.Random.Range(0, startPositions.Count)];
+ }
+ else
+ {
+ Transform startPosition = startPositions[startPositionIndex];
+ startPositionIndex = (startPositionIndex + 1) % startPositions.Count;
+ return startPosition;
+ }
+ }
+
#endregion
#region Server Internal Message Handlers
void OnServerConnectInternal(NetworkConnection conn, ConnectMessage connectMsg)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnServerConnectInternal");
+ logger.Log("NetworkManager.OnServerConnectInternal");
if (authenticator != null)
{
@@ -823,7 +1145,7 @@ void OnServerConnectInternal(NetworkConnection conn, ConnectMessage connectMsg)
// called after successful authentication
void OnServerAuthenticated(NetworkConnection conn)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnServerAuthenticated");
+ logger.Log("NetworkManager.OnServerAuthenticated");
// set connection to authenticated
conn.isAuthenticated = true;
@@ -840,58 +1162,52 @@ void OnServerAuthenticated(NetworkConnection conn)
void OnServerDisconnectInternal(NetworkConnection conn, DisconnectMessage msg)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnServerDisconnectInternal");
+ logger.Log("NetworkManager.OnServerDisconnectInternal");
OnServerDisconnect(conn);
}
void OnServerReadyMessageInternal(NetworkConnection conn, ReadyMessage msg)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnServerReadyMessageInternal");
+ logger.Log("NetworkManager.OnServerReadyMessageInternal");
OnServerReady(conn);
}
- void OnServerAddPlayerInternal(NetworkConnection conn, AddPlayerMessage extraMessage)
+ void OnServerAddPlayerInternal(NetworkConnection conn, AddPlayerMessage msg)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnServerAddPlayer");
+ logger.Log("NetworkManager.OnServerAddPlayer");
if (autoCreatePlayer && playerPrefab == null)
{
- Debug.LogError("The PlayerPrefab is empty on the NetworkManager. Please setup a PlayerPrefab object.");
+ logger.LogError("The PlayerPrefab is empty on the NetworkManager. Please setup a PlayerPrefab object.");
return;
}
if (autoCreatePlayer && playerPrefab.GetComponent() == null)
{
- Debug.LogError("The PlayerPrefab does not have a NetworkIdentity. Please add a NetworkIdentity to the player prefab.");
+ logger.LogError("The PlayerPrefab does not have a NetworkIdentity. Please add a NetworkIdentity to the player prefab.");
return;
}
if (conn.identity != null)
{
- Debug.LogError("There is already a player for this connection.");
+ logger.LogError("There is already a player for this connection.");
return;
}
-#pragma warning disable CS0618 // Type or member is obsolete
- OnServerAddPlayer(conn, extraMessage);
-#pragma warning restore CS0618 // Type or member is obsolete
+ OnServerAddPlayer(conn);
}
- void OnServerRemovePlayerMessageInternal(NetworkConnection conn, RemovePlayerMessage msg)
- {
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnServerRemovePlayerMessageInternal");
-
- if (conn.identity != null)
- {
- OnServerRemovePlayer(conn, conn.identity);
- conn.identity = null;
- }
- }
+ // Deprecated 5/2/2020
+ ///
+ /// Obsolete: Removed as a security risk. Use NetworkServer.RemovePlayerForConnection instead.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Removed as a security risk. Use NetworkServer.RemovePlayerForConnection(NetworkConnection conn, bool keepAuthority = false) instead", true)]
+ void OnServerRemovePlayerMessageInternal(NetworkConnection conn, RemovePlayerMessage msg) { }
void OnServerErrorInternal(NetworkConnection conn, ErrorMessage msg)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnServerErrorInternal");
- OnServerError(conn, msg.error);
+ logger.Log("NetworkManager.OnServerErrorInternal");
+ OnServerError(conn, msg.value);
}
#endregion
@@ -900,7 +1216,7 @@ void OnServerErrorInternal(NetworkConnection conn, ErrorMessage msg)
void OnClientConnectInternal(NetworkConnection conn, ConnectMessage message)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnClientConnectInternal");
+ logger.Log("NetworkManager.OnClientConnectInternal");
if (authenticator != null)
{
@@ -917,14 +1233,13 @@ void OnClientConnectInternal(NetworkConnection conn, ConnectMessage message)
// called after successful authentication
void OnClientAuthenticated(NetworkConnection conn)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnClientAuthenticated");
+ logger.Log("NetworkManager.OnClientAuthenticated");
// set connection to authenticated
conn.isAuthenticated = true;
// proceed with the login handshake by calling OnClientConnect
- string loadedSceneName = SceneManager.GetActiveScene().name;
- if (string.IsNullOrEmpty(onlineScene) || onlineScene == offlineScene || loadedSceneName == onlineScene)
+ if (string.IsNullOrEmpty(onlineScene) || onlineScene == offlineScene || IsSceneActive(onlineScene))
{
clientLoadedScene = false;
OnClientConnect(conn);
@@ -932,19 +1247,20 @@ void OnClientAuthenticated(NetworkConnection conn)
else
{
// will wait for scene id to come from the server.
+ clientLoadedScene = true;
clientReadyConnection = conn;
}
}
void OnClientDisconnectInternal(NetworkConnection conn, DisconnectMessage msg)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnClientDisconnectInternal");
+ logger.Log("NetworkManager.OnClientDisconnectInternal");
OnClientDisconnect(conn);
}
void OnClientNotReadyMessageInternal(NetworkConnection conn, NotReadyMessage msg)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnClientNotReadyMessageInternal");
+ logger.Log("NetworkManager.OnClientNotReadyMessageInternal");
ClientScene.ready = false;
OnClientNotReady(conn);
@@ -954,17 +1270,17 @@ void OnClientNotReadyMessageInternal(NetworkConnection conn, NotReadyMessage msg
void OnClientErrorInternal(NetworkConnection conn, ErrorMessage msg)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager:OnClientErrorInternal");
- OnClientError(conn, msg.error);
+ logger.Log("NetworkManager:OnClientErrorInternal");
+ OnClientError(conn, msg.value);
}
void OnClientSceneInternal(NetworkConnection conn, SceneMessage msg)
{
- if (LogFilter.Debug) Debug.Log("NetworkManager.OnClientSceneInternal");
+ logger.Log("NetworkManager.OnClientSceneInternal");
if (NetworkClient.isConnected && !NetworkServer.active)
{
- ClientChangeScene(msg.sceneName, msg.sceneOperation);
+ ClientChangeScene(msg.sceneName, msg.sceneOperation, msg.customHandling);
}
}
@@ -987,7 +1303,7 @@ public virtual void OnServerConnect(NetworkConnection conn) { }
public virtual void OnServerDisconnect(NetworkConnection conn)
{
NetworkServer.DestroyPlayerForConnection(conn);
- if (LogFilter.Debug) Debug.Log("OnServerDisconnect: Client disconnected.");
+ logger.Log("OnServerDisconnect: Client disconnected.");
}
///
@@ -1000,23 +1316,11 @@ public virtual void OnServerReady(NetworkConnection conn)
if (conn.identity == null)
{
// this is now allowed (was not for a while)
- if (LogFilter.Debug) Debug.Log("Ready with no player object");
+ logger.Log("Ready with no player object");
}
NetworkServer.SetClientReady(conn);
}
- ///
- /// Obsolete: Override instead.
- /// See Custom Players for details.
- ///
- /// Connection from client.
- /// An extra message object passed for the new player.
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Override OnServerAddPlayer(NetworkConnection conn) instead. See https://mirror-networking.com/docs/Guides/GameObjects/SpawnPlayerCustom.html for details.")]
- public virtual void OnServerAddPlayer(NetworkConnection conn, AddPlayerMessage extraMessage)
- {
- OnServerAddPlayer(conn);
- }
-
///
/// Called on the server when a client adds a new player with ClientScene.AddPlayer.
/// The default implementation for this function creates a new player object from the playerPrefab.
@@ -1032,44 +1336,12 @@ public virtual void OnServerAddPlayer(NetworkConnection conn)
NetworkServer.AddPlayerForConnection(conn, player);
}
+ // Deprecated 5/2/2020
///
- /// This finds a spawn position based on NetworkStartPosition objects in the scene.
- /// This is used by the default implementation of OnServerAddPlayer.
- ///
- /// Returns the transform to spawn a player at, or null.
- public Transform GetStartPosition()
- {
- // first remove any dead transforms
- startPositions.RemoveAll(t => t == null);
-
- if (startPositions.Count == 0)
- return null;
-
- if (playerSpawnMethod == PlayerSpawnMethod.Random)
- {
- return startPositions[UnityEngine.Random.Range(0, startPositions.Count)];
- }
- else
- {
- Transform startPosition = startPositions[startPositionIndex];
- startPositionIndex = (startPositionIndex + 1) % startPositions.Count;
- return startPosition;
- }
- }
-
- ///
- /// Called on the server when a client removes a player.
- /// The default implementation of this function destroys the corresponding player object.
+ /// Obsolete: Removed as a security risk. Use NetworkServer.RemovePlayerForConnection instead.
///
- /// The connection to remove the player from.
- /// The player controller to remove.
- public virtual void OnServerRemovePlayer(NetworkConnection conn, NetworkIdentity player)
- {
- if (player.gameObject != null)
- {
- NetworkServer.Destroy(player.gameObject);
- }
- }
+ [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Removed as a security risk. Use NetworkServer.RemovePlayerForConnection(NetworkConnection conn, bool keepAuthority = false) instead", true)]
+ public virtual void OnServerRemovePlayer(NetworkConnection conn, NetworkIdentity player) { }
///
/// Called on the server when a network error occurs for a client connection.
@@ -1102,13 +1374,16 @@ public virtual void OnServerSceneChanged(string sceneName) { }
/// Connection to the server.
public virtual void OnClientConnect(NetworkConnection conn)
{
+ // OnClientConnect by default calls AddPlayer but it should not do
+ // that when we have online/offline scenes. so we need the
+ // clientLoadedScene flag to prevent it.
if (!clientLoadedScene)
{
// Ready/AddPlayer is usually triggered by a scene load completing. if no scene was loaded, then Ready/AddPlayer it here instead.
if (!ClientScene.ready) ClientScene.Ready(conn);
if (autoCreatePlayer)
{
- ClientScene.AddPlayer();
+ ClientScene.AddPlayer(conn);
}
}
}
@@ -1137,14 +1412,14 @@ public virtual void OnClientError(NetworkConnection conn, int errorCode) { }
/// Connection to the server.
public virtual void OnClientNotReady(NetworkConnection conn) { }
+ // Deprecated 12/22/2019
///
- /// Obsolete: Use instead.).
+ /// Obsolete: Use OnClientChangeScene(string, SceneOperation, bool) instead.
///
- /// Name of the scene that's about to be loaded
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Override OnClientChangeScene(string newSceneName, SceneOperation sceneOperation) instead")]
- public virtual void OnClientChangeScene(string newSceneName)
+ [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Override OnClientChangeScene(string newSceneName, SceneOperation sceneOperation, bool customHandling) instead", true)]
+ public virtual void OnClientChangeScene(string newSceneName, SceneOperation sceneOperation)
{
- OnClientChangeScene(newSceneName, SceneOperation.Normal);
+ OnClientChangeScene(newSceneName, sceneOperation, false);
}
///
@@ -1153,7 +1428,8 @@ public virtual void OnClientChangeScene(string newSceneName)
///
/// Name of the scene that's about to be loaded
/// Scene operation that's about to happen
- public virtual void OnClientChangeScene(string newSceneName, SceneOperation sceneOperation) { }
+ /// true to indicate that scene loading will be handled through overrides
+ public virtual void OnClientChangeScene(string newSceneName, SceneOperation sceneOperation, bool customHandling) { }
///
/// Called on clients when a scene has completed loaded, when the scene load was initiated by the server.
@@ -1165,10 +1441,11 @@ public virtual void OnClientSceneChanged(NetworkConnection conn)
// always become ready.
if (!ClientScene.ready) ClientScene.Ready(conn);
- if (autoCreatePlayer && ClientScene.localPlayer == null)
+ // Only call AddPlayer for normal scene changes, not additive load/unload
+ if (clientSceneOperation == SceneOperation.Normal && autoCreatePlayer && ClientScene.localPlayer == null)
{
// add player if existing one is null
- ClientScene.AddPlayer();
+ ClientScene.AddPlayer(conn);
}
}
@@ -1192,23 +1469,10 @@ public virtual void OnStartHost() { }
///
public virtual void OnStartServer() { }
- ///
- /// Obsolete: Use instead of OnStartClient(NetworkClient client).
- /// All NetworkClient functions are static now, so you can use NetworkClient.Send(message) instead of client.Send(message) directly now.
- ///
- /// The NetworkClient object that was started.
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use OnStartClient() instead of OnStartClient(NetworkClient client). All NetworkClient functions are static now, so you can use NetworkClient.Send(message) instead of client.Send(message) directly now.")]
- public virtual void OnStartClient(NetworkClient client) { }
-
///
/// This is invoked when the client is started.
///
- public virtual void OnStartClient()
- {
-#pragma warning disable CS0618 // Type or member is obsolete
- OnStartClient(NetworkClient.singleton);
-#pragma warning restore CS0618 // Type or member is obsolete
- }
+ public virtual void OnStartClient() { }
///
/// This is called when a server is stopped - including when a host is stopped.
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManager.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManager.cs.meta
index 3ca7c55..0a7564a 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManager.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManager.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManagerHUD.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManagerHUD.cs
index 76fb6fa..8131e30 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManagerHUD.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManagerHUD.cs
@@ -9,6 +9,7 @@ namespace Mirror
/// An extension for the NetworkManager that displays a default HUD for controlling the network state of the game.
/// This component also shows useful internal state for the networking system in the inspector window of the editor. It allows users to view connections, networked objects, message handlers, and packet statistics. This information can be helpful when debugging networked games.
///
+ [DisallowMultipleComponent]
[AddComponentMenu("Network/NetworkManagerHUD")]
[RequireComponent(typeof(NetworkManager))]
[EditorBrowsable(EditorBrowsableState.Never)]
@@ -45,84 +46,115 @@ void OnGUI()
GUILayout.BeginArea(new Rect(10 + offsetX, 40 + offsetY, 215, 9999));
if (!NetworkClient.isConnected && !NetworkServer.active)
{
- if (!NetworkClient.active)
+ StartButtons();
+ }
+ else
+ {
+ StatusLabels();
+ }
+
+ // client ready
+ if (NetworkClient.isConnected && !ClientScene.ready)
+ {
+ if (GUILayout.Button("Client Ready"))
{
- // LAN Host
- if (Application.platform != RuntimePlatform.WebGLPlayer)
- {
- if (GUILayout.Button("LAN Host"))
- {
- manager.StartHost();
- }
- }
+ ClientScene.Ready(NetworkClient.connection);
- // LAN Client + IP
- GUILayout.BeginHorizontal();
- if (GUILayout.Button("LAN Client"))
+ if (ClientScene.localPlayer == null)
{
- manager.StartClient();
+ ClientScene.AddPlayer(NetworkClient.connection);
}
- manager.networkAddress = GUILayout.TextField(manager.networkAddress);
- GUILayout.EndHorizontal();
+ }
+ }
- // LAN Server Only
- if (Application.platform == RuntimePlatform.WebGLPlayer)
- {
- // cant be a server in webgl build
- GUILayout.Box("( WebGL cannot be server )");
- }
- else
+ StopButtons();
+
+ GUILayout.EndArea();
+ }
+
+ void StartButtons()
+ {
+ if (!NetworkClient.active)
+ {
+ // Server + Client
+ if (Application.platform != RuntimePlatform.WebGLPlayer)
+ {
+ if (GUILayout.Button("Host (Server + Client)"))
{
- if (GUILayout.Button("LAN Server Only")) manager.StartServer();
+ manager.StartHost();
}
}
+
+ // Client + IP
+ GUILayout.BeginHorizontal();
+ if (GUILayout.Button("Client"))
+ {
+ manager.StartClient();
+ }
+ manager.networkAddress = GUILayout.TextField(manager.networkAddress);
+ GUILayout.EndHorizontal();
+
+ // Server Only
+ if (Application.platform == RuntimePlatform.WebGLPlayer)
+ {
+ // cant be a server in webgl build
+ GUILayout.Box("( WebGL cannot be server )");
+ }
else
{
- // Connecting
- GUILayout.Label("Connecting to " + manager.networkAddress + "..");
- if (GUILayout.Button("Cancel Connection Attempt"))
- {
- manager.StopClient();
- }
+ if (GUILayout.Button("Server Only")) manager.StartServer();
}
}
else
{
- // server / client status message
- if (NetworkServer.active)
+ // Connecting
+ GUILayout.Label("Connecting to " + manager.networkAddress + "..");
+ if (GUILayout.Button("Cancel Connection Attempt"))
{
- GUILayout.Label("Server: active. Transport: " + Transport.activeTransport);
+ manager.StopClient();
}
- if (NetworkClient.isConnected)
+ }
+ }
+
+ void StatusLabels()
+ {
+ // server / client status message
+ if (NetworkServer.active)
+ {
+ GUILayout.Label("Server: active. Transport: " + Transport.activeTransport);
+ }
+ if (NetworkClient.isConnected)
+ {
+ GUILayout.Label("Client: address=" + manager.networkAddress);
+ }
+ }
+
+ void StopButtons()
+ {
+ // stop host if host mode
+ if (NetworkServer.active && NetworkClient.isConnected)
+ {
+ if (GUILayout.Button("Stop Host"))
{
- GUILayout.Label("Client: address=" + manager.networkAddress);
+ manager.StopHost();
}
}
-
- // client ready
- if (NetworkClient.isConnected && !ClientScene.ready)
+ // stop client if client-only
+ else if (NetworkClient.isConnected)
{
- if (GUILayout.Button("Client Ready"))
+ if (GUILayout.Button("Stop Client"))
{
- ClientScene.Ready(NetworkClient.connection);
-
- if (ClientScene.localPlayer == null)
- {
- ClientScene.AddPlayer();
- }
+ manager.StopClient();
}
}
-
- // stop
- if (NetworkServer.active || NetworkClient.isConnected)
+ // stop server if server-only
+ else if (NetworkServer.active)
{
- if (GUILayout.Button("Stop"))
+ if (GUILayout.Button("Stop Server"))
{
- manager.StopHost();
+ manager.StopServer();
}
}
-
- GUILayout.EndArea();
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManagerHUD.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManagerHUD.cs.meta
index fa08c3d..a720b9c 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManagerHUD.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkManagerHUD.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkMessage.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkMessage.cs
index c41c45b..300b10e 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkMessage.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkMessage.cs
@@ -1,25 +1 @@
-namespace Mirror
-{
- public struct NetworkMessage
- {
- public NetworkConnection conn;
- public NetworkReader reader;
- public int channelId;
-
- public TMsg ReadMessage() where TMsg : IMessageBase, new()
- {
- // Normally I would just do:
- // TMsg msg = new TMsg();
- // but mono calls an expensive method Activator.CreateInstance
- // For value types this is unnecesary, just use the default value
- TMsg msg = typeof(TMsg).IsValueType ? default(TMsg) : new TMsg();
- msg.Deserialize(reader);
- return msg;
- }
-
- public void ReadMessage(TMsg msg) where TMsg : IMessageBase
- {
- msg.Deserialize(reader);
- }
- }
-}
+// file removed 03/17/2020
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReader.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReader.cs
index 0466984..37f9014 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReader.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReader.cs
@@ -16,44 +16,30 @@ namespace Mirror
// Note: This class is intended to be extremely pedantic, and
// throw exceptions whenever stuff is going slightly wrong.
// The exceptions will be handled in NetworkServer/NetworkClient.
+ ///
+ /// Binary stream Reader. Supports simple types, buffers, arrays, structs, and nested types
+ /// Use NetworkReaderPool.GetReader to reduce memory allocation
+ ///
public class NetworkReader
{
// internal buffer
// byte[] pointer would work, but we use ArraySegment to also support
// the ArraySegment constructor
- ArraySegment buffer;
+ internal ArraySegment buffer;
// 'int' is the best type for .Position. 'short' is too small if we send >32kb which would result in negative .Position
// -> converting long to int is fine until 2GB of data (MAX_INT), so we don't have to worry about overflows here
public int Position;
public int Length => buffer.Count;
- internal bool pooled;
- internal readonly bool reusable;
- public NetworkReader(byte[] bytes, bool reusable = false)
+ public NetworkReader(byte[] bytes)
{
buffer = new ArraySegment(bytes);
- Position = 0;
- this.reusable = reusable;
}
- public NetworkReader(ArraySegment segment, bool reusable = false)
+ public NetworkReader(ArraySegment segment)
{
buffer = segment;
- Position = 0;
- this.reusable = reusable;
- }
-
- internal void SetBuffer(byte[] bytes)
- {
- buffer = new ArraySegment(bytes);
- Position = 0;
- }
-
- internal void SetBuffer(ArraySegment segment)
- {
- buffer = segment;
- Position = 0;
}
public byte ReadByte()
@@ -67,7 +53,8 @@ public byte ReadByte()
public int ReadInt32() => (int)ReadUInt32();
public uint ReadUInt32()
{
- uint value = ReadByte();
+ uint value = 0;
+ value |= ReadByte();
value |= (uint)(ReadByte() << 8);
value |= (uint)(ReadByte() << 16);
value |= (uint)(ReadByte() << 24);
@@ -76,7 +63,8 @@ public uint ReadUInt32()
public long ReadInt64() => (long)ReadUInt64();
public ulong ReadUInt64()
{
- ulong value = ReadByte();
+ ulong value = 0;
+ value |= ReadByte();
value |= ((ulong)ReadByte()) << 8;
value |= ((ulong)ReadByte()) << 16;
value |= ((ulong)ReadByte()) << 24;
@@ -126,6 +114,8 @@ public override string ToString()
// but they do all need to be extensions.
public static class NetworkReaderExtensions
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkReaderExtensions));
+
// cache encoding instead of creating it each time
// 1000 readers before: 1MB GC, 30ms
// 1000 readers after: 0.8MB GC, 18ms
@@ -138,14 +128,16 @@ public static class NetworkReaderExtensions
public static short ReadInt16(this NetworkReader reader) => (short)reader.ReadUInt16();
public static ushort ReadUInt16(this NetworkReader reader)
{
- ushort value = reader.ReadByte();
+ ushort value = 0;
+ value |= reader.ReadByte();
value |= (ushort)(reader.ReadByte() << 8);
return value;
}
public static int ReadInt32(this NetworkReader reader) => (int)reader.ReadUInt32();
public static uint ReadUInt32(this NetworkReader reader)
{
- uint value = reader.ReadByte();
+ uint value = 0;
+ value |= reader.ReadByte();
value |= (uint)(reader.ReadByte() << 8);
value |= (uint)(reader.ReadByte() << 16);
value |= (uint)(reader.ReadByte() << 24);
@@ -154,7 +146,8 @@ public static uint ReadUInt32(this NetworkReader reader)
public static long ReadInt64(this NetworkReader reader) => (long)reader.ReadUInt64();
public static ulong ReadUInt64(this NetworkReader reader)
{
- ulong value = reader.ReadByte();
+ ulong value = 0;
+ value |= reader.ReadByte();
value |= ((ulong)reader.ReadByte()) << 8;
value |= ((ulong)reader.ReadByte()) << 16;
value |= ((ulong)reader.ReadByte()) << 24;
@@ -166,17 +159,21 @@ public static ulong ReadUInt64(this NetworkReader reader)
}
public static float ReadSingle(this NetworkReader reader)
{
- UIntFloat converter = new UIntFloat {intValue = reader.ReadUInt32()};
+ UIntFloat converter = new UIntFloat();
+ converter.intValue = reader.ReadUInt32();
return converter.floatValue;
}
public static double ReadDouble(this NetworkReader reader)
{
- UIntDouble converter = new UIntDouble {longValue = reader.ReadUInt64()};
+ UIntDouble converter = new UIntDouble();
+ converter.longValue = reader.ReadUInt64();
return converter.doubleValue;
}
public static decimal ReadDecimal(this NetworkReader reader)
{
- UIntDecimal converter = new UIntDecimal {longValue1 = reader.ReadUInt64(), longValue2 = reader.ReadUInt64()};
+ UIntDecimal converter = new UIntDecimal();
+ converter.longValue1 = reader.ReadUInt64();
+ converter.longValue2 = reader.ReadUInt64();
return converter.decimalValue;
}
@@ -187,13 +184,8 @@ public static string ReadString(this NetworkReader reader)
// read number of bytes
ushort size = reader.ReadUInt16();
- switch (size)
- {
- case 0:
- return null;
- case 1:
- return "";
- }
+ if (size == 0)
+ return null;
int realSize = size - 1;
@@ -214,7 +206,7 @@ public static string ReadString(this NetworkReader reader)
public static byte[] ReadBytesAndSize(this NetworkReader reader)
{
// count = 0 means the array was null
- // otherwise count -1 is the length of the array
+ // otherwise count -1 is the length of the array
uint count = reader.ReadPackedUInt32();
return count == 0 ? null : reader.ReadBytes(checked((int)(count - 1u)));
}
@@ -348,21 +340,43 @@ public static byte[] ReadBytes(this NetworkReader reader, int count)
}
public static Guid ReadGuid(this NetworkReader reader) => new Guid(reader.ReadBytes(16));
- public static Transform ReadTransform(this NetworkReader reader) => reader.ReadNetworkIdentity()?.transform;
- public static GameObject ReadGameObject(this NetworkReader reader) => reader.ReadNetworkIdentity()?.gameObject;
+ public static Transform ReadTransform(this NetworkReader reader)
+ {
+ // Dont use null propagation here as it could lead to MissingReferenceException
+ NetworkIdentity networkIdentity = reader.ReadNetworkIdentity();
+ return networkIdentity != null ? networkIdentity.transform : null;
+ }
+
+ public static GameObject ReadGameObject(this NetworkReader reader)
+ {
+ // Dont use null propagation here as it could lead to MissingReferenceException
+ NetworkIdentity networkIdentity = reader.ReadNetworkIdentity();
+ return networkIdentity != null ? networkIdentity.gameObject : null;
+ }
public static NetworkIdentity ReadNetworkIdentity(this NetworkReader reader)
{
uint netId = reader.ReadPackedUInt32();
- if (netId == 0) return null;
+ if (netId == 0)
+ return null;
if (NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity identity))
{
return identity;
}
- if (LogFilter.Debug) Debug.Log("ReadNetworkIdentity netId:" + netId + " not found in spawned");
+ if (logger.WarnEnabled()) logger.LogFormat(LogType.Warning, "ReadNetworkIdentity netId:{0} not found in spawned", netId);
return null;
}
+
+ public static Uri ReadUri(this NetworkReader reader)
+ {
+ return new Uri(reader.ReadString());
+ }
+
+ public static void ReadMessage(this NetworkReader reader, T msg) where T : IMessageBase
+ {
+ msg.Deserialize(reader);
+ }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReaderPool.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReaderPool.cs
index 3fe6cbf..4c80a6a 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReaderPool.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReaderPool.cs
@@ -1,56 +1,135 @@
using System;
-using System.Collections.Generic;
using UnityEngine;
namespace Mirror
{
+ ///
+ /// NetworkReader to be used with NetworkReaderPool
+ ///
+ public class PooledNetworkReader : NetworkReader, IDisposable
+ {
+ internal PooledNetworkReader(byte[] bytes) : base(bytes) { }
+
+ internal PooledNetworkReader(ArraySegment segment) : base(segment) { }
+
+ public void Dispose()
+ {
+ NetworkReaderPool.Recycle(this);
+ }
+ }
+
+ ///
+ /// Pool of NetworkReaders
+ /// Use this pool instead of NetworkReader to reduce memory allocation
+ /// Use Capacity to change size of pool
+ ///
public static class NetworkReaderPool
{
- // reuse all readers, saves tons of memory allocations in hotpath
- static readonly Stack readerPool = new Stack();
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkReaderPool), LogType.Error);
- public static NetworkReader GetReader(byte[] data)
+ ///
+ /// Size of the pool
+ /// If pool is too small getting readers will causes memory allocation
+ /// Default value: 100
+ ///
+ public static int Capacity
{
- if (readerPool.Count != 0)
+ get => pool.Length;
+ set
{
- NetworkReader reader = readerPool.Pop();
- reader.pooled = false;
- // reset cached writer length and position
- reader.SetBuffer(data);
- return reader;
- }
+ // resize the array
+ Array.Resize(ref pool, value);
- return new NetworkReader(data, true);
+ // if capacity is smaller than before, then we need to adjust
+ // 'next' so it doesn't point to an index out of range
+ // -> if we set '0' then next = min(_, 0-1) => -1
+ // -> if we set '2' then next = min(_, 2-1) => 1
+ next = Mathf.Min(next, pool.Length - 1);
+ }
}
- public static NetworkReader GetReader(ArraySegment data)
+ ///
+ /// Mirror usually only uses up to 4 readers in nested usings,
+ /// 100 is a good margin for edge cases when users need a lot readers at
+ /// the same time.
+ ///
+ /// keep in mind, most entries of the pool will be null in most cases
+ ///
+ ///
+ /// Note: we use an Array instead of a Stack because it's significantly
+ /// faster: https://github.com/vis2k/Mirror/issues/1614
+ static PooledNetworkReader[] pool = new PooledNetworkReader[100];
+
+ static int next = -1;
+
+ ///
+ /// Get the next reader in the pool
+ /// If pool is empty, creates a new Reader
+ ///
+ public static PooledNetworkReader GetReader(byte[] bytes)
{
- if (readerPool.Count != 0)
+ if (next == -1)
{
- NetworkReader reader = readerPool.Pop();
- reader.pooled = false;
- // reset cached writer length and position
- reader.SetBuffer(data);
- return reader;
+ return new PooledNetworkReader(bytes);
}
- return new NetworkReader(data, true);
+ PooledNetworkReader reader = pool[next];
+ pool[next] = null;
+ next--;
+
+ // reset buffer
+ SetBuffer(reader, bytes);
+ return reader;
}
- public static void Recycle(NetworkReader reader)
+ ///
+ /// Get the next reader in the pool
+ /// If pool is empty, creates a new Reader
+ ///
+ public static PooledNetworkReader GetReader(ArraySegment segment)
{
- if (reader == null)
+ if (next == -1)
{
- Debug.LogWarning("Recycling null readers is not allowed, please check your code!");
- return;
+ return new PooledNetworkReader(segment);
}
- if (reader.reusable && !reader.pooled)
+ PooledNetworkReader reader = pool[next];
+ pool[next] = null;
+ next--;
+
+ // reset buffer
+ SetBuffer(reader, segment);
+ return reader;
+ }
+
+ ///
+ /// Puts reader back into pool
+ /// When pool is full, the extra reader is left for the GC
+ ///
+ public static void Recycle(PooledNetworkReader reader)
+ {
+ if (next < pool.Length - 1)
+ {
+ next++;
+ pool[next] = reader;
+ }
+ else
{
- reader.pooled = true;
- reader.SetBuffer(default(ArraySegment));
- readerPool.Push(reader);
+ logger.LogWarning("NetworkReaderPool.Recycle, Pool was full leaving extra reader for GC");
}
}
+
+ // SetBuffer methods mirror constructor for ReaderPool
+ static void SetBuffer(NetworkReader reader, byte[] bytes)
+ {
+ reader.buffer = new ArraySegment(bytes);
+ reader.Position = 0;
+ }
+
+ static void SetBuffer(NetworkReader reader, ArraySegment segment)
+ {
+ reader.buffer = segment;
+ reader.Position = 0;
+ }
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReaderPool.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReaderPool.cs.meta
index 451cd45..a1ef25e 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReaderPool.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkReaderPool.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: b7f586ce6f07b6f47926a5ef00431198
+guid: 2bacff63613ad634a98f9e4d15d29dbf
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkServer.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkServer.cs
index 9c68ab0..974aa61 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkServer.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkServer.cs
@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
+using Mirror.RemoteCalls;
using UnityEngine;
namespace Mirror
{
///
- /// The NetworkServer uses a NetworkServerSimple for basic network functionality and adds more game-like functionality.
+ /// The NetworkServer.
///
///
/// NetworkServer handles remote connections from remote clients via a NetworkServerSimple instance, and also has a local connection for a local client.
@@ -17,24 +18,35 @@ namespace Mirror
///
public static class NetworkServer
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkServer));
+
static bool initialized;
static int maxConnections;
+ ///
+ /// The connection to the host mode client (if any).
+ ///
// original HLAPI has .localConnections list with only m_LocalConnection in it
// (for backwards compatibility because they removed the real localConnections list a while ago)
// => removed it for easier code. use .localConnection now!
- public static NetworkConnection localConnection { get; private set; }
+ public static NetworkConnectionToClient localConnection { get; private set; }
+
+ ///
+ /// True is a local client is currently active on the server.
+ /// This will be true for "Hosts" on hosted server games.
+ ///
+ public static bool localClientActive => localConnection != null;
///
/// A list of local connections on the server.
///
- public static Dictionary connections = new Dictionary();
+ public static Dictionary connections = new Dictionary();
///
/// Dictionary of the message handlers registered with the server.
/// The key to the dictionary is the message Id.
///
- public static Dictionary handlers = new Dictionary();
+ static Dictionary handlers = new Dictionary();
///
/// If you enable this, the server will not listen for incoming connections on the regular network port.
@@ -49,17 +61,28 @@ public static class NetworkServer
public static bool active { get; private set; }
///
- /// True is a local client is currently active on the server.
- /// This will be true for "Hosts" on hosted server games.
+ /// Should the server disconnect remote connections that have gone silent for more than Server Idle Timeout?
+ /// This value is initially set from NetworkManager in SetupServer and can be changed at runtime
+ ///
+ public static bool disconnectInactiveConnections;
+
+ ///
+ /// Timeout in seconds since last message from a client after which server will auto-disconnect.
+ /// This value is initially set from NetworkManager in SetupServer and can be changed at runtime
+ /// By default, clients send at least a Ping message every 2 seconds.
+ /// The Host client is immune from idle timeout disconnection.
+ /// Default value is 60 seconds.
///
- public static bool localClientActive { get; private set; }
+ public static float disconnectInactiveTimeout = 60f;
// cache the Send(connectionIds) list to avoid allocating each time
- static List connectionIdsCache = new List();
+ static readonly List connectionIdsCache = new List();
+ // Deprecated 02/23/2020
///
/// Reset the NetworkServer singleton.
///
+ [Obsolete("NetworkServer.Reset was used to reset the singleton, but all it does is set active to false ever since we made NetworkServer static. Use StopServer to stop the server, or Shutdown to fully reset the server.")]
public static void Reset()
{
active = false;
@@ -74,12 +97,12 @@ public static void Shutdown()
{
DisconnectAll();
- if (dontListen)
- {
- // was never started, so dont stop
- }
- else
+ if (!dontListen)
{
+ // stop the server.
+ // we do NOT call Transport.Shutdown, because someone only
+ // called NetworkServer.Shutdown. we can't assume that the
+ // client is supposed to be shut down too!
Transport.activeTransport.ServerStop();
}
@@ -92,17 +115,40 @@ public static void Shutdown()
}
dontListen = false;
active = false;
+ handlers.Clear();
+ CleanupNetworkIdentities();
NetworkIdentity.ResetNextNetworkId();
}
+ static void CleanupNetworkIdentities()
+ {
+ foreach (NetworkIdentity identity in NetworkIdentity.spawned.Values)
+ {
+ if (identity != null)
+ {
+ if (identity.sceneId != 0)
+ {
+ identity.Reset();
+ identity.gameObject.SetActive(false);
+ }
+ else
+ {
+ GameObject.Destroy(identity.gameObject);
+ }
+ }
+ }
+
+ NetworkIdentity.spawned.Clear();
+ }
+
static void Initialize()
{
if (initialized)
return;
initialized = true;
- if (LogFilter.Debug) Debug.Log("NetworkServer Created version " + Version.Current);
+ if (logger.LogEnabled()) logger.Log("NetworkServer Created version " + Version.Current);
//Make sure connections are cleared in case any old connections references exist from previous sessions
connections.Clear();
@@ -116,7 +162,6 @@ internal static void RegisterMessageHandlers()
{
RegisterHandler(OnClientReadyMessage);
RegisterHandler(OnCommandMessage);
- RegisterHandler(OnRemovePlayerMessage);
RegisterHandler(NetworkTime.OnServerPing, false);
}
@@ -124,8 +169,7 @@ internal static void RegisterMessageHandlers()
/// Start the server, setting the maximum number of connections.
///
/// Maximum number of allowed connections
- ///
- public static bool Listen(int maxConns)
+ public static void Listen(int maxConns)
{
Initialize();
maxConnections = maxConns;
@@ -134,12 +178,11 @@ public static bool Listen(int maxConns)
if (!dontListen)
{
Transport.activeTransport.ServerStart();
- if (LogFilter.Debug) Debug.Log("Server started listening");
+ logger.Log("Server started listening");
}
active = true;
RegisterMessageHandlers();
- return true;
}
///
@@ -148,7 +191,7 @@ public static bool Listen(int maxConns)
///
/// Network connection to add.
/// True if added.
- public static bool AddConnection(NetworkConnection conn)
+ public static bool AddConnection(NetworkConnectionToClient conn)
{
if (!connections.ContainsKey(conn.connectionId))
{
@@ -177,12 +220,11 @@ internal static void SetLocalConnection(ULocalConnectionToClient conn)
{
if (localConnection != null)
{
- Debug.LogError("Local Connection already exists");
+ logger.LogError("Local Connection already exists");
return;
}
localConnection = conn;
- OnConnected(localConnection);
}
internal static void RemoveLocalConnection()
@@ -193,22 +235,16 @@ internal static void RemoveLocalConnection()
localConnection.Dispose();
localConnection = null;
}
- localClientActive = false;
RemoveConnection(0);
}
- internal static void ActivateLocalClientScene()
+ public static void ActivateHostScene()
{
- if (localClientActive)
- return;
-
- // ClientScene for a local connection is becoming active. any spawned objects need to be started as client objects
- localClientActive = true;
foreach (NetworkIdentity identity in NetworkIdentity.spawned.Values)
{
if (!identity.isClient)
{
- if (LogFilter.Debug) Debug.Log("ActivateClientScene " + identity.netId + " " + identity);
+ if (logger.LogEnabled()) logger.Log("ActivateHostScene " + identity.netId + " " + identity);
identity.OnStartClient();
}
@@ -217,39 +253,67 @@ internal static void ActivateLocalClientScene()
// this is like SendToReady - but it doesn't check the ready flag on the connection.
// this is used for ObjectDestroy messages.
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("use SendToObservers instead")]
- static bool SendToObservers(NetworkIdentity identity, short msgType, MessageBase msg)
+ static void SendToObservers(NetworkIdentity identity, T msg, int channelId = Channels.DefaultReliable) where T : IMessageBase
{
- if (LogFilter.Debug) Debug.Log("Server.SendToObservers id:" + msgType);
+ if (logger.LogEnabled()) logger.Log("Server.SendToObservers id:" + typeof(T));
if (identity != null && identity.observers != null)
{
- // pack message into byte[] once
- byte[] bytes = MessagePacker.PackMessage((ushort)msgType, msg);
-
- // send to all observers
- bool result = true;
- foreach (KeyValuePair kvp in identity.observers)
+ // get writer from pool
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
{
- result &= kvp.Value.Send(new ArraySegment(bytes));
+ // pack message into byte[] once
+ MessagePacker.Pack(msg, writer);
+ ArraySegment segment = writer.ToArraySegment();
+
+ // filter and then send to all internet connections at once
+ // -> makes code more complicated, but is HIGHLY worth it to
+ // avoid allocations, allow for multicast, etc.
+ connectionIdsCache.Clear();
+ foreach (KeyValuePair kvp in identity.observers)
+ {
+ // use local connection directly because it doesn't send via transport
+ if (kvp.Value is ULocalConnectionToClient)
+ kvp.Value.Send(segment);
+ // gather all internet connections
+ else
+ connectionIdsCache.Add(kvp.Key);
+ }
+
+ // send to all internet connections at once
+ if (connectionIdsCache.Count > 0)
+ {
+ NetworkConnectionToClient.Send(connectionIdsCache, segment, channelId);
+ }
+
+ NetworkDiagnostics.OnSend(msg, channelId, segment.Count, identity.observers.Count);
}
- return result;
}
- return false;
}
- // this is like SendToReady - but it doesn't check the ready flag on the connection.
- // this is used for ObjectDestroy messages.
- static bool SendToObservers(NetworkIdentity identity, T msg) where T: IMessageBase
+ ///
+ /// Send a message to all connected clients, both ready and not-ready.
+ /// See NetworkConnection.isReady
+ ///
+ /// Message type
+ /// Message
+ /// Transport channel to use
+ /// Indicates if only ready clients should receive the message
+ ///
+ public static bool SendToAll(T msg, int channelId = Channels.DefaultReliable, bool sendToReadyOnly = false) where T : IMessageBase
{
- if (LogFilter.Debug) Debug.Log("Server.SendToObservers id:" + typeof(T));
-
- if (identity != null && identity.observers != null)
+ if (!active)
{
- // get writer from pool
- NetworkWriter writer = NetworkWriterPool.GetWriter();
+ logger.LogWarning("Can not send using NetworkServer.SendToAll(T msg) because NetworkServer is not active");
+ return false;
+ }
+
+ if (logger.LogEnabled()) logger.Log("Server.SendToAll id:" + typeof(T));
- // pack message into byte[] once
+ // get writer from pool
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
+ {
+ // pack message only once
MessagePacker.Pack(msg, writer);
ArraySegment segment = writer.ToArraySegment();
@@ -258,11 +322,17 @@ static bool SendToObservers(NetworkIdentity identity, T msg) where T: IMessag
// avoid allocations, allow for multicast, etc.
connectionIdsCache.Clear();
bool result = true;
- foreach (KeyValuePair kvp in identity.observers)
+ int count = 0;
+ foreach (KeyValuePair kvp in connections)
{
+ if (sendToReadyOnly && !kvp.Value.isReady)
+ continue;
+
+ count++;
+
// use local connection directly because it doesn't send via transport
if (kvp.Value is ULocalConnectionToClient)
- result &= localConnection.Send(segment);
+ result &= kvp.Value.Send(segment);
// gather all internet connections
else
connectionIdsCache.Add(kvp.Key);
@@ -270,176 +340,104 @@ static bool SendToObservers(NetworkIdentity identity, T msg) where T: IMessag
// send to all internet connections at once
if (connectionIdsCache.Count > 0)
- result &= NetworkConnection.Send(connectionIdsCache, segment);
- NetworkDiagnostics.OnSend(msg, Channels.DefaultReliable, segment.Count, identity.observers.Count);
-
- // recycle writer and return
- NetworkWriterPool.Recycle(writer);
- return result;
- }
- return false;
- }
-
- ///
- /// Obsolete: Use instead.
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use SendToAll instead.")]
- public static bool SendToAll(int msgType, MessageBase msg, int channelId = Channels.DefaultReliable)
- {
- if (LogFilter.Debug) Debug.Log("Server.SendToAll id:" + msgType);
+ {
+ result &= NetworkConnectionToClient.Send(connectionIdsCache, segment, channelId);
+ }
- // pack message into byte[] once
- byte[] bytes = MessagePacker.PackMessage((ushort)msgType, msg);
+ NetworkDiagnostics.OnSend(msg, channelId, segment.Count, count);
- // send to all
- bool result = true;
- foreach (KeyValuePair kvp in connections)
- {
- result &= kvp.Value.Send(new ArraySegment(bytes), channelId);
+ return result;
}
- return result;
}
///
- /// Send a message structure with the given type number to all connected clients.
- /// This applies to clients that are ready and not-ready.
+ /// Send a message to only clients which are ready.
+ /// See NetworkConnection.isReady
///
/// Message type.
- /// Message structure.
+ /// Message
/// Transport channel to use
///
- public static bool SendToAll(T msg, int channelId = Channels.DefaultReliable) where T : IMessageBase
- {
- if (LogFilter.Debug) Debug.Log("Server.SendToAll id:" + typeof(T));
-
-
- // get writer from pool
- NetworkWriter writer = NetworkWriterPool.GetWriter();
-
- // pack message only once
- MessagePacker.Pack(msg, writer);
- ArraySegment segment = writer.ToArraySegment();
-
- // filter and then send to all internet connections at once
- // -> makes code more complicated, but is HIGHLY worth it to
- // avoid allocations, allow for multicast, etc.
- connectionIdsCache.Clear();
- bool result = true;
- foreach (KeyValuePair kvp in connections)
- {
- // use local connection directly because it doesn't send via transport
- if (kvp.Value is ULocalConnectionToClient)
- result &= localConnection.Send(segment);
- // gather all internet connections
- else
- connectionIdsCache.Add(kvp.Key);
- }
-
- // send to all internet connections at once
- if (connectionIdsCache.Count > 0)
- result &= NetworkConnection.Send(connectionIdsCache, segment);
- NetworkDiagnostics.OnSend(msg, channelId, segment.Count, connections.Count);
-
- // recycle writer and return
- NetworkWriterPool.Recycle(writer);
- return result;
- }
-
- ///
- /// Obsolete: Use instead.
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use SendToReady instead.")]
- public static bool SendToReady(NetworkIdentity identity, short msgType, MessageBase msg, int channelId = Channels.DefaultReliable)
+ public static bool SendToReady(T msg, int channelId = Channels.DefaultReliable) where T : IMessageBase
{
- if (LogFilter.Debug) Debug.Log("Server.SendToReady msgType:" + msgType);
-
- if (identity != null && identity.observers != null)
+ if (!active)
{
- // pack message into byte[] once
- byte[] bytes = MessagePacker.PackMessage((ushort)msgType, msg);
-
- // send to all ready observers
- bool result = true;
- foreach (KeyValuePair kvp in identity.observers)
- {
- if (kvp.Value.isReady)
- {
- result &= kvp.Value.Send(new ArraySegment(bytes), channelId);
- }
- }
- return result;
+ logger.LogWarning("Can not send using NetworkServer.SendToReady(T msg) because NetworkServer is not active");
+ return false;
}
- return false;
+
+ return SendToAll(msg, channelId, true);
}
///
- /// Send a message structure with the given type number to only clients which are ready.
- /// See Networking.NetworkClient.Ready.
+ /// Send a message to only clients which are ready with option to include the owner of the object identity.
+ /// See NetworkConnection.isReady
///
/// Message type.
- ///
- /// Message structure.
- /// Send to observers including self..
+ /// Identity of the owner
+ /// Message
+ /// Should the owner of the object be included
/// Transport channel to use
///
- public static bool SendToReady(NetworkIdentity identity, T msg, bool includeSelf = true, int channelId = Channels.DefaultReliable) where T : IMessageBase
+ public static bool SendToReady(NetworkIdentity identity, T msg, bool includeOwner = true, int channelId = Channels.DefaultReliable) where T : IMessageBase
{
- if (LogFilter.Debug) Debug.Log("Server.SendToReady msgType:" + typeof(T));
+ if (logger.LogEnabled()) logger.Log("Server.SendToReady msgType:" + typeof(T));
if (identity != null && identity.observers != null)
{
// get writer from pool
- NetworkWriter writer = NetworkWriterPool.GetWriter();
-
- // pack message only once
- MessagePacker.Pack(msg, writer);
- ArraySegment segment = writer.ToArraySegment();
-
- // filter and then send to all internet connections at once
- // -> makes code more complicated, but is HIGHLY worth it to
- // avoid allocations, allow for multicast, etc.
- connectionIdsCache.Clear();
- bool result = true;
- int count = 0;
- foreach (KeyValuePair kvp in identity.observers)
+ using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
{
- bool isSelf = kvp.Value == identity.connectionToClient;
- if ((!isSelf || includeSelf) &&
- kvp.Value.isReady)
+ // pack message only once
+ MessagePacker.Pack(msg, writer);
+ ArraySegment segment = writer.ToArraySegment();
+
+ // filter and then send to all internet connections at once
+ // -> makes code more complicated, but is HIGHLY worth it to
+ // avoid allocations, allow for multicast, etc.
+ connectionIdsCache.Clear();
+ bool result = true;
+ int count = 0;
+ foreach (KeyValuePair kvp in identity.observers)
{
- count++;
+ bool isOwner = kvp.Value == identity.connectionToClient;
+ if ((!isOwner || includeOwner) && kvp.Value.isReady)
+ {
+ count++;
+
+ // use local connection directly because it doesn't send via transport
+ if (kvp.Value is ULocalConnectionToClient)
+ result &= kvp.Value.Send(segment);
+ // gather all internet connections
+ else
+ connectionIdsCache.Add(kvp.Key);
+ }
+ }
- // use local connection directly because it doesn't send via transport
- if (kvp.Value is ULocalConnectionToClient)
- result &= localConnection.Send(segment);
- // gather all internet connections
- else
- connectionIdsCache.Add(kvp.Key);
+ // send to all internet connections at once
+ if (connectionIdsCache.Count > 0)
+ {
+ result &= NetworkConnectionToClient.Send(connectionIdsCache, segment, channelId);
}
- }
- // send to all internet connections at once
- if (connectionIdsCache.Count > 0)
- result &= NetworkConnection.Send(connectionIdsCache, segment);
- NetworkDiagnostics.OnSend(msg, channelId, segment.Count, count);
+ NetworkDiagnostics.OnSend(msg, channelId, segment.Count, count);
- // recycle writer and return
- NetworkWriterPool.Recycle(writer);
- return result;
+ return result;
+ }
}
return false;
}
///
- /// Send a message structure with the given type number to only clients which are ready.
- /// See Networking.NetworkClient.Ready.
+ /// Send a message to only clients which are ready including the owner of the object identity.
+ /// See NetworkConnection.isReady
///
- /// Message type.
- ///
- /// Message structure.
+ /// Message type
+ /// identity of the object
+ /// Message
/// Transport channel to use
///
- public static bool SendToReady(NetworkIdentity identity, T msg, int channelId = Channels.DefaultReliable) where T : IMessageBase
+ public static bool SendToReady(NetworkIdentity identity, T msg, int channelId) where T : IMessageBase
{
return SendToReady(identity, msg, true, channelId);
}
@@ -454,7 +452,6 @@ public static void DisconnectAll()
localConnection = null;
active = false;
- localClientActive = false;
}
///
@@ -467,7 +464,7 @@ public static void DisconnectAllConnections()
{
conn.Disconnect();
// call OnDisconnected unless local player in host mode
- if (conn.connectionId != 0)
+ if (conn.connectionId != NetworkConnection.LocalConnectionId)
OnDisconnected(conn);
conn.Dispose();
}
@@ -475,35 +472,49 @@ public static void DisconnectAllConnections()
}
// The user should never need to pump the update loop manually
- internal static void Update()
+ public static void Update()
{
if (!active)
return;
+ // Check for dead clients but exclude the host client because it
+ // doesn't ping itself and therefore may appear inactive.
+ if (disconnectInactiveConnections)
+ {
+ foreach (NetworkConnectionToClient conn in connections.Values)
+ {
+ if (!conn.IsClientAlive())
+ {
+ logger.LogWarning($"Disconnecting {conn} for inactivity!");
+ conn.Disconnect();
+ }
+ }
+ }
+
// update all server objects
foreach (KeyValuePair kvp in NetworkIdentity.spawned)
{
if (kvp.Value != null && kvp.Value.gameObject != null)
{
- kvp.Value.MirrorUpdate();
+ kvp.Value.ServerUpdate();
}
else
{
// spawned list should have no null entries because we
// always call Remove in OnObjectDestroy everywhere.
- Debug.LogWarning("Found 'null' entry in spawned list for netId=" + kvp.Key + ". Please call NetworkServer.Destroy to destroy networked objects. Don't use GameObject.Destroy.");
+ logger.LogWarning("Found 'null' entry in spawned list for netId=" + kvp.Key + ". Please call NetworkServer.Destroy to destroy networked objects. Don't use GameObject.Destroy.");
}
}
}
static void OnConnected(int connectionId)
{
- if (LogFilter.Debug) Debug.Log("Server accepted client:" + connectionId);
+ if (logger.LogEnabled()) logger.Log("Server accepted client:" + connectionId);
// connectionId needs to be > 0 because 0 is reserved for local player
if (connectionId <= 0)
{
- Debug.LogError("Server.HandleConnect: invalid connectionId: " + connectionId + " . Needs to be >0, because 0 is reserved for local player.");
+ logger.LogError("Server.HandleConnect: invalid connectionId: " + connectionId + " . Needs to be >0, because 0 is reserved for local player.");
Transport.activeTransport.ServerDisconnect(connectionId);
return;
}
@@ -512,7 +523,7 @@ static void OnConnected(int connectionId)
if (connections.ContainsKey(connectionId))
{
Transport.activeTransport.ServerDisconnect(connectionId);
- if (LogFilter.Debug) Debug.Log("Server connectionId " + connectionId + " already in use. kicked client:" + connectionId);
+ if (logger.LogEnabled()) logger.Log("Server connectionId " + connectionId + " already in use. kicked client:" + connectionId);
return;
}
@@ -523,39 +534,36 @@ static void OnConnected(int connectionId)
// Transport can't do that)
if (connections.Count < maxConnections)
{
- // get ip address from connection
- string address = Transport.activeTransport.ServerGetClientAddress(connectionId);
-
// add connection
- NetworkConnection conn = new NetworkConnection(address, connectionId);
+ NetworkConnectionToClient conn = new NetworkConnectionToClient(connectionId);
OnConnected(conn);
}
else
{
// kick
Transport.activeTransport.ServerDisconnect(connectionId);
- if (LogFilter.Debug) Debug.Log("Server full, kicked client:" + connectionId);
+ if (logger.LogEnabled()) logger.Log("Server full, kicked client:" + connectionId);
}
}
- static void OnConnected(NetworkConnection conn)
+ internal static void OnConnected(NetworkConnectionToClient conn)
{
- if (LogFilter.Debug) Debug.Log("Server accepted client:" + conn.connectionId);
+ if (logger.LogEnabled()) logger.Log("Server accepted client:" + conn);
// add connection and invoke connected event
AddConnection(conn);
conn.InvokeHandler(new ConnectMessage(), -1);
}
- static void OnDisconnected(int connectionId)
+ internal static void OnDisconnected(int connectionId)
{
- if (LogFilter.Debug) Debug.Log("Server disconnect client:" + connectionId);
+ if (logger.LogEnabled()) logger.Log("Server disconnect client:" + connectionId);
- if (connections.TryGetValue(connectionId, out NetworkConnection conn))
+ if (connections.TryGetValue(connectionId, out NetworkConnectionToClient conn))
{
conn.Disconnect();
RemoveConnection(connectionId);
- if (LogFilter.Debug) Debug.Log("Server lost client:" + connectionId);
+ if (logger.LogEnabled()) logger.Log("Server lost client:" + connectionId);
OnDisconnected(conn);
}
@@ -564,47 +572,42 @@ static void OnDisconnected(int connectionId)
static void OnDisconnected(NetworkConnection conn)
{
conn.InvokeHandler(new DisconnectMessage(), -1);
- if (LogFilter.Debug) Debug.Log("Server lost client:" + conn.connectionId);
+ if (logger.LogEnabled()) logger.Log("Server lost client:" + conn);
}
static void OnDataReceived(int connectionId, ArraySegment data, int channelId)
{
- if (connections.TryGetValue(connectionId, out NetworkConnection conn))
+ if (connections.TryGetValue(connectionId, out NetworkConnectionToClient conn))
{
conn.TransportReceive(data, channelId);
}
else
{
- Debug.LogError("HandleData Unknown connectionId:" + connectionId);
+ logger.LogError("HandleData Unknown connectionId:" + connectionId);
}
}
static void OnError(int connectionId, Exception exception)
{
// TODO Let's discuss how we will handle errors
- Debug.LogException(exception);
+ logger.LogException(exception);
}
///
- /// Obsolete: Use instead.
+ /// Register a handler for a particular message type.
+ /// There are several system message types which you can add handlers for. You can also add your own message types.
///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use RegisterHandler(Action, bool) instead.")]
- public static void RegisterHandler(int msgType, NetworkMessageDelegate handler)
+ /// Message type
+ /// Function handler which will be invoked when this message type is received.
+ /// True if the message requires an authenticated connection
+ public static void RegisterHandler(Action handler, bool requireAuthentication = true) where T : IMessageBase, new()
{
+ int msgType = MessagePacker.GetId();
if (handlers.ContainsKey(msgType))
{
- if (LogFilter.Debug) Debug.Log("NetworkServer.RegisterHandler replacing " + msgType);
+ logger.LogWarning($"NetworkServer.RegisterHandler replacing handler for {typeof(T).FullName}, id={msgType}. If replacement is intentional, use ReplaceHandler instead to avoid this warning.");
}
- handlers[msgType] = handler;
- }
-
- ///
- /// Obsolete: Use instead.
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use RegisterHandler(Action, bool) instead.")]
- public static void RegisterHandler(MsgType msgType, NetworkMessageDelegate handler)
- {
- RegisterHandler((int)msgType, handler);
+ handlers[msgType] = MessagePacker.MessageHandler(handler, requireAuthentication);
}
///
@@ -612,34 +615,36 @@ public static void RegisterHandler(MsgType msgType, NetworkMessageDelegate handl
/// There are several system message types which you can add handlers for. You can also add your own message types.
///
/// Message type
- /// Function handler which will be invoked for when this message type is received.
+ /// Function handler which will be invoked when this message type is received.
/// True if the message requires an authenticated connection
- public static void RegisterHandler(Action handler, bool requireAuthentication = true) where T: IMessageBase, new()
+ public static void RegisterHandler(Action handler, bool requireAuthentication = true) where T : IMessageBase, new()
{
- int msgType = MessagePacker.GetId();
- if (handlers.ContainsKey(msgType))
- {
- if (LogFilter.Debug) Debug.Log("NetworkServer.RegisterHandler replacing " + msgType);
- }
- handlers[msgType] = MessagePacker.MessageHandler(handler, requireAuthentication);
+ RegisterHandler((_, value) => { handler(value); }, requireAuthentication);
}
///
- /// Obsolete: Use instead.
+ /// Replaces a handler for a particular message type.
+ /// See also RegisterHandler(T)(Action(NetworkConnection, T), bool)
///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use UnregisterHandler instead.")]
- public static void UnregisterHandler(int msgType)
+ /// Message type
+ /// Function handler which will be invoked when this message type is received.
+ /// True if the message requires an authenticated connection
+ public static void ReplaceHandler(Action handler, bool requireAuthentication = true) where T : IMessageBase, new()
{
- handlers.Remove(msgType);
+ int msgType = MessagePacker.GetId();
+ handlers[msgType] = MessagePacker.MessageHandler(handler, requireAuthentication);
}
///
- /// Obsolete: Use instead.
+ /// Replaces a handler for a particular message type.
+ /// See also RegisterHandler(T)(Action(NetworkConnection, T), bool)
///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use UnregisterHandler instead.")]
- public static void UnregisterHandler(MsgType msgType)
+ /// Message type
+ /// Function handler which will be invoked when this message type is received.
+ /// True if the message requires an authenticated connection
+ public static void ReplaceHandler(Action handler, bool requireAuthentication = true) where T : IMessageBase, new()
{
- UnregisterHandler((int)msgType);
+ ReplaceHandler((_, value) => { handler(value); }, requireAuthentication);
}
///
@@ -660,68 +665,21 @@ public static void ClearHandlers()
handlers.Clear();
}
- ///
- /// Obsolete: Use instead.
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use SendToClient instead.")]
- public static void SendToClient(int connectionId, int msgType, MessageBase msg)
- {
- if (connections.TryGetValue(connectionId, out NetworkConnection conn))
- {
- conn.Send(msgType, msg);
- return;
- }
- Debug.LogError("Failed to send message to connection ID '" + connectionId + ", not found in connection list");
- }
-
- ///
- /// Send a message to the client which owns the given connection ID.
- /// It accepts the connection ID as a parameter as well as a message and MsgType. Remember to set the client up for receiving the messages by using NetworkClient.RegisterHandler. Also, for user messages you must use a MsgType with a higher ID number than MsgType.Highest.
- ///
- /// Message type
- /// Client connection ID.
- /// Message struct to send
- public static void SendToClient(int connectionId, T msg) where T : IMessageBase
- {
- if (connections.TryGetValue(connectionId, out NetworkConnection conn))
- {
- conn.Send(msg);
- return;
- }
- Debug.LogError("Failed to send message to connection ID '" + connectionId + ", not found in connection list");
- }
-
- ///
- /// Obsolete: Use instead.
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use SendToClientOfPlayer instead.")]
- public static void SendToClientOfPlayer(NetworkIdentity identity, int msgType, MessageBase msg)
- {
- if (identity != null)
- {
- identity.connectionToClient.Send(msgType, msg);
- }
- else
- {
- Debug.LogError("SendToClientOfPlayer: player has no NetworkIdentity: " + identity.name);
- }
- }
-
///
/// send this message to the player only
///
/// Message type
///
///
- public static void SendToClientOfPlayer(NetworkIdentity identity, T msg) where T: IMessageBase
+ public static void SendToClientOfPlayer(NetworkIdentity identity, T msg, int channelId = Channels.DefaultReliable) where T : IMessageBase
{
if (identity != null)
{
- identity.connectionToClient.Send(msg);
+ identity.connectionToClient.Send(msg, channelId);
}
else
{
- Debug.LogError("SendToClientOfPlayer: player has no NetworkIdentity: " + identity.name);
+ logger.LogError("SendToClientOfPlayer: player has no NetworkIdentity: " + identity);
}
}
@@ -732,14 +690,15 @@ public static void SendToClientOfPlayer(NetworkIdentity identity, T msg) wher
/// Connection which is adding the player.
/// Player object spawned for the player.
///
- ///
- public static bool ReplacePlayerForConnection(NetworkConnection conn, GameObject player, Guid assetId)
+ /// Does the previous player remain attached to this connection?
+ /// True if connection was successfully replaced for player.
+ public static bool ReplacePlayerForConnection(NetworkConnection conn, GameObject player, Guid assetId, bool keepAuthority = false)
{
if (GetNetworkIdentity(player, out NetworkIdentity identity))
{
identity.assetId = assetId;
}
- return InternalReplacePlayerForConnection(conn, player);
+ return InternalReplacePlayerForConnection(conn, player, keepAuthority);
}
///
@@ -748,10 +707,11 @@ public static bool ReplacePlayerForConnection(NetworkConnection conn, GameObject
///
/// Connection which is adding the player.
/// Player object spawned for the player.
- ///
- public static bool ReplacePlayerForConnection(NetworkConnection conn, GameObject player)
+ /// Does the previous player remain attached to this connection?
+ /// True if connection was successfully replaced for player.
+ public static bool ReplacePlayerForConnection(NetworkConnection conn, GameObject player, bool keepAuthority = false)
{
- return InternalReplacePlayerForConnection(conn, player);
+ return InternalReplacePlayerForConnection(conn, player, keepAuthority);
}
///
@@ -761,7 +721,7 @@ public static bool ReplacePlayerForConnection(NetworkConnection conn, GameObject
/// Connection which is adding the player.
/// Player object spawned for the player.
///
- ///
+ /// True if connection was sucessfully added for a connection.
public static bool AddPlayerForConnection(NetworkConnection conn, GameObject player, Guid assetId)
{
if (GetNetworkIdentity(player, out NetworkIdentity identity))
@@ -773,7 +733,7 @@ public static bool AddPlayerForConnection(NetworkConnection conn, GameObject pla
static void SpawnObserversForConnection(NetworkConnection conn)
{
- if (LogFilter.Debug) Debug.Log("Spawning " + NetworkIdentity.spawned.Count + " objects for conn " + conn.connectionId);
+ if (logger.LogEnabled()) logger.Log("Spawning " + NetworkIdentity.spawned.Count + " objects for conn " + conn);
if (!conn.isReady)
{
@@ -789,9 +749,10 @@ static void SpawnObserversForConnection(NetworkConnection conn)
// internally sends a spawn message for each one to the connection.
foreach (NetworkIdentity identity in NetworkIdentity.spawned.Values)
{
- if (identity.gameObject.activeSelf) //TODO this is different // try with far away ones in ummorpg!
+ // try with far away ones in ummorpg!
+ if (identity.gameObject.activeSelf) //TODO this is different
{
- if (LogFilter.Debug) Debug.Log("Sending spawn message for current server objects name='" + identity.name + "' netId=" + identity.netId + " sceneId=" + identity.sceneId);
+ if (logger.LogEnabled()) logger.Log("Sending spawn message for current server objects name='" + identity.name + "' netId=" + identity.netId + " sceneId=" + identity.sceneId);
bool visible = identity.OnCheckObserver(conn);
if (visible)
@@ -813,21 +774,20 @@ static void SpawnObserversForConnection(NetworkConnection conn)
///
/// Connection which is adding the player.
/// Player object spawned for the player.
- ///
+ /// True if connection was successfully added for a connection.
public static bool AddPlayerForConnection(NetworkConnection conn, GameObject player)
{
NetworkIdentity identity = player.GetComponent();
if (identity == null)
{
- Debug.Log("AddPlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to " + player);
+ logger.LogWarning("AddPlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to " + player);
return false;
}
- identity.Reset();
// cannot have a player object in "Add" version
if (conn.identity != null)
{
- Debug.Log("AddPlayer: player object already exists");
+ logger.Log("AddPlayer: player object already exists");
return false;
}
@@ -836,93 +796,69 @@ public static bool AddPlayerForConnection(NetworkConnection conn, GameObject pla
conn.identity = identity;
// Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients)
- identity.connectionToClient = conn;
-
- // set ready if not set yet
- SetClientReady(conn);
+ identity.SetClientOwner(conn);
- if (SetupLocalPlayerForConnection(conn, identity))
+ // special case, we are in host mode, set hasAuthority to true so that all overrides see it
+ if (conn is ULocalConnectionToClient)
{
- return true;
+ identity.hasAuthority = true;
+ ClientScene.InternalAddPlayer(identity);
}
- if (LogFilter.Debug) Debug.Log("Adding new playerGameObject object netId: " + identity.netId + " asset ID " + identity.assetId);
+ // set ready if not set yet
+ SetClientReady(conn);
- FinishPlayerForConnection(identity, player);
- if (identity.localPlayerAuthority)
- {
- identity.SetClientOwner(conn);
- }
+ if (logger.LogEnabled()) logger.Log("Adding new playerGameObject object netId: " + identity.netId + " asset ID " + identity.assetId);
+
+ Respawn(identity);
return true;
}
- static bool SetupLocalPlayerForConnection(NetworkConnection conn, NetworkIdentity identity)
+ static void Respawn(NetworkIdentity identity)
{
- if (LogFilter.Debug) Debug.Log("NetworkServer SetupLocalPlayerForConnection netID:" + identity.netId);
-
- if (conn is ULocalConnectionToClient)
+ if (identity.netId == 0)
{
- if (LogFilter.Debug) Debug.Log("NetworkServer AddPlayer handling ULocalConnectionToClient");
-
- // Spawn this player for other players, instead of SpawnObject:
- if (identity.netId == 0)
- {
- // it is allowed to provide an already spawned object as the new player object.
- // so dont spawn it again.
- identity.OnStartServer(true);
- }
- identity.RebuildObservers(true);
- SendSpawnMessage(identity, null);
-
- // Set up local player instance on the client instance and update local object map
- NetworkClient.AddLocalPlayer(identity);
- identity.SetClientOwner(conn);
-
- // Trigger OnAuthority
- identity.ForceAuthority(true);
-
- // Trigger OnStartLocalPlayer
- identity.SetLocalPlayer();
- return true;
+ // If the object has not been spawned, then do a full spawn and update observers
+ Spawn(identity.gameObject, identity.connectionToClient);
}
- return false;
- }
-
- static void FinishPlayerForConnection(NetworkIdentity identity, GameObject playerGameObject)
- {
- if (identity.netId == 0)
+ else
{
- // it is allowed to provide an already spawned object as the new player object.
- // so dont spawn it again.
- Spawn(playerGameObject);
+ // otherwise just replace his data
+ SendSpawnMessage(identity, identity.connectionToClient);
}
}
- internal static bool InternalReplacePlayerForConnection(NetworkConnection conn, GameObject player)
+ internal static bool InternalReplacePlayerForConnection(NetworkConnection conn, GameObject player, bool keepAuthority)
{
NetworkIdentity identity = player.GetComponent();
if (identity == null)
{
- Debug.LogError("ReplacePlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to " + player);
+ logger.LogError("ReplacePlayer: playerGameObject has no NetworkIdentity. Please add a NetworkIdentity to " + player);
return false;
}
- //NOTE: there can be an existing player
- if (LogFilter.Debug) Debug.Log("NetworkServer ReplacePlayer");
-
- // is there already an owner that is a different object??
- if (conn.identity != null)
+ if (identity.connectionToClient != null && identity.connectionToClient != conn)
{
- conn.identity.SetNotLocalPlayer();
- conn.identity.clientAuthorityOwner = null;
+ logger.LogError("Cannot replace player for connection. New player is already owned by a different connection" + player);
+ return false;
}
+ //NOTE: there can be an existing player
+ logger.Log("NetworkServer ReplacePlayer");
+
+ NetworkIdentity previousPlayer = conn.identity;
+
conn.identity = identity;
// Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients)
- identity.connectionToClient = conn;
+ identity.SetClientOwner(conn);
- //NOTE: DONT set connection ready.
+ // special case, we are in host mode, set hasAuthority to true so that all overrides see it
+ if (conn is ULocalConnectionToClient)
+ {
+ identity.hasAuthority = true;
+ ClientScene.InternalAddPlayer(identity);
+ }
// add connection to observers AFTER the playerController was set.
// by definition, there is nothing to observe if there is no player
@@ -931,29 +867,22 @@ internal static bool InternalReplacePlayerForConnection(NetworkConnection conn,
// IMPORTANT: do this in AddPlayerForConnection & ReplacePlayerForConnection!
SpawnObserversForConnection(conn);
- if (LogFilter.Debug) Debug.Log("NetworkServer ReplacePlayer setup local");
+ if (logger.LogEnabled()) logger.Log("Replacing playerGameObject object netId: " + player.GetComponent().netId + " asset ID " + player.GetComponent().assetId);
- if (SetupLocalPlayerForConnection(conn, identity))
- {
- return true;
- }
+ Respawn(identity);
- if (LogFilter.Debug) Debug.Log("Replacing playerGameObject object netId: " + player.GetComponent().netId + " asset ID " + player.GetComponent().assetId);
+ if (!keepAuthority)
+ previousPlayer.RemoveClientAuthority();
- FinishPlayerForConnection(identity, player);
- if (identity.localPlayerAuthority)
- {
- identity.SetClientOwner(conn);
- }
return true;
}
- static bool GetNetworkIdentity(GameObject go, out NetworkIdentity identity)
+ internal static bool GetNetworkIdentity(GameObject go, out NetworkIdentity identity)
{
identity = go.GetComponent();
if (identity == null)
{
- Debug.LogError("GameObject " + go.name + " doesn't have NetworkIdentity.");
+ logger.LogError("GameObject " + go.name + " doesn't have NetworkIdentity.");
return false;
}
return true;
@@ -966,7 +895,7 @@ static bool GetNetworkIdentity(GameObject go, out NetworkIdentity identity)
/// The connection of the client to make ready.
public static void SetClientReady(NetworkConnection conn)
{
- if (LogFilter.Debug) Debug.Log("SetClientReadyInternal for conn:" + conn.connectionId);
+ if (logger.LogEnabled()) logger.Log("SetClientReadyInternal for conn:" + conn);
// set ready
conn.isReady = true;
@@ -1012,7 +941,7 @@ public static void SetClientNotReady(NetworkConnection conn)
{
if (conn.isReady)
{
- if (LogFilter.Debug) Debug.Log("PlayerNotReady " + conn);
+ if (logger.LogEnabled()) logger.Log("PlayerNotReady " + conn);
conn.isReady = false;
conn.RemoveObservers();
@@ -1023,21 +952,36 @@ public static void SetClientNotReady(NetworkConnection conn)
// default ready handler.
static void OnClientReadyMessage(NetworkConnection conn, ReadyMessage msg)
{
- if (LogFilter.Debug) Debug.Log("Default handler for ready message from " + conn);
+ if (logger.LogEnabled()) logger.Log("Default handler for ready message from " + conn);
SetClientReady(conn);
}
- // default remove player handler
- static void OnRemovePlayerMessage(NetworkConnection conn, RemovePlayerMessage msg)
+ // Deprecated 5/2/2020
+ ///
+ /// Obsolete: Removed as a security risk. Use NetworkServer.RemovePlayerForConnection instead.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Removed as a security risk. Use NetworkServer.RemovePlayerForConnection(NetworkConnection conn, bool keepAuthority = false) instead", true)]
+ static void OnRemovePlayerMessage(NetworkConnection conn, RemovePlayerMessage msg) { }
+
+ ///
+ /// Removes the player object from the connection
+ ///
+ /// The connection of the client to remove from
+ /// Indicates whether the server object should be destroyed
+ public static void RemovePlayerForConnection(NetworkConnection conn, bool destroyServerObject)
{
if (conn.identity != null)
{
- Destroy(conn.identity.gameObject);
+ if (destroyServerObject)
+ Destroy(conn.identity.gameObject);
+ else
+ UnSpawn(conn.identity.gameObject);
+
conn.identity = null;
}
else
{
- Debug.LogError("Received remove player message but connection has no player");
+ if (logger.LogEnabled()) logger.Log($"Connection {conn} has no identity");
}
}
@@ -1046,50 +990,62 @@ static void OnCommandMessage(NetworkConnection conn, CommandMessage msg)
{
if (!NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
{
- Debug.LogWarning("Spawned object not found when handling Command message [netId=" + msg.netId + "]");
+ logger.LogWarning("Spawned object not found when handling Command message [netId=" + msg.netId + "]");
return;
}
+ CommandInfo commandInfo = identity.GetCommandInfo(msg.componentIndex, msg.functionHash);
+
// Commands can be for player objects, OR other objects with client-authority
// -> so if this connection's controller has a different netId then
// only allow the command if clientAuthorityOwner
- if (conn.identity != null && conn.identity.netId != identity.netId)
+ bool needAuthority = !commandInfo.ignoreAuthority;
+ if (needAuthority && identity.connectionToClient != conn)
{
- if (identity.clientAuthorityOwner != conn)
- {
- Debug.LogWarning("Command for object without authority [netId=" + msg.netId + "]");
- return;
- }
+ logger.LogWarning("Command for object without authority [netId=" + msg.netId + "]");
+ return;
}
- if (LogFilter.Debug) Debug.Log("OnCommandMessage for netId=" + msg.netId + " conn=" + conn);
- NetworkReader reader = NetworkReaderPool.GetReader(msg.payload);
- identity.HandleCommand(msg.componentIndex, msg.functionHash, reader);
- NetworkReaderPool.Recycle(reader);
+ if (logger.LogEnabled()) logger.Log("OnCommandMessage for netId=" + msg.netId + " conn=" + conn);
+
+ using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload))
+ identity.HandleCommand(msg.componentIndex, msg.functionHash, networkReader, conn as NetworkConnectionToClient);
}
- internal static void SpawnObject(GameObject obj)
+ internal static void SpawnObject(GameObject obj, NetworkConnection ownerConnection)
{
if (!active)
{
- Debug.LogError("SpawnObject for " + obj + ", NetworkServer is not active. Cannot spawn objects without an active server.");
+ logger.LogError("SpawnObject for " + obj + ", NetworkServer is not active. Cannot spawn objects without an active server.");
return;
}
NetworkIdentity identity = obj.GetComponent();
if (identity == null)
{
- Debug.LogError("SpawnObject " + obj + " has no NetworkIdentity. Please add a NetworkIdentity to " + obj);
+ logger.LogError("SpawnObject " + obj + " has no NetworkIdentity. Please add a NetworkIdentity to " + obj);
return;
}
- identity.Reset();
- identity.OnStartServer(false);
+ if (identity.SpawnedFromInstantiate)
+ {
+ // Using Instantiate on SceneObject is not allowed, so stop spawning here
+ // NetworkIdentity.Awake already logs error, no need to log a second error here
+ return;
+ }
+
+ identity.connectionToClient = (NetworkConnectionToClient)ownerConnection;
+
+ // special case to make sure hasAuthority is set
+ // on start server in host mode
+ if (ownerConnection is ULocalConnectionToClient)
+ identity.hasAuthority = true;
- if (LogFilter.Debug) Debug.Log("SpawnObject instance ID " + identity.netId + " asset ID " + identity.assetId);
+ identity.OnStartServer();
+
+ if (logger.LogEnabled()) logger.Log("SpawnObject instance ID " + identity.netId + " asset ID " + identity.assetId);
identity.RebuildObservers(true);
- //SendSpawnMessage(objNetworkIdentity, null);
}
internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnection conn)
@@ -1097,109 +1053,58 @@ internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnectio
if (identity.serverOnly)
return;
- if (LogFilter.Debug) Debug.Log("Server SendSpawnMessage: name=" + identity.name + " sceneId=" + identity.sceneId.ToString("X") + " netid=" + identity.netId); // for easier debugging
+ // for easier debugging
+ if (logger.LogEnabled()) logger.Log("Server SendSpawnMessage: name=" + identity.name + " sceneId=" + identity.sceneId.ToString("X") + " netid=" + identity.netId);
// one writer for owner, one for observers
- NetworkWriter ownerWriter = NetworkWriterPool.GetWriter();
- NetworkWriter observersWriter = NetworkWriterPool.GetWriter();
+ using (PooledNetworkWriter ownerWriter = NetworkWriterPool.GetWriter(), observersWriter = NetworkWriterPool.GetWriter())
+ {
+ bool isOwner = identity.connectionToClient == conn;
+ ArraySegment payload = CreateSpawnMessagePayload(isOwner, identity, ownerWriter, observersWriter);
- // serialize all components with initialState = true
- // (can be null if has none)
- identity.OnSerializeAllSafely(true, ownerWriter, out int ownerWritten, observersWriter, out int observersWritten);
-
- // convert to ArraySegment to avoid reader allocations
- // (need to handle null case too)
- ArraySegment ownerSegment = ownerWritten > 0 ? ownerWriter.ToArraySegment() : default;
- ArraySegment observersSegment = observersWritten > 0 ? observersWriter.ToArraySegment() : default;
-
- // 'identity' is a prefab that should be spawned
- if (identity.sceneId == 0)
- {
- SpawnPrefabMessage msg = new SpawnPrefabMessage
+ SpawnMessage msg = new SpawnMessage
{
netId = identity.netId,
- owner = conn?.identity == identity,
+ isLocalPlayer = conn.identity == identity,
+ isOwner = isOwner,
+ sceneId = identity.sceneId,
assetId = identity.assetId,
// use local values for VR support
position = identity.transform.localPosition,
rotation = identity.transform.localRotation,
- scale = identity.transform.localScale
- };
+ scale = identity.transform.localScale,
- // conn is != null when spawning it for a client
- if (conn != null)
- {
- // use owner segment if 'conn' owns this identity, otherwise
- // use observers segment
- bool isOwner = identity.connectionToClient == conn;
- msg.payload = isOwner ? ownerSegment : observersSegment;
+ payload = payload,
+ };
- conn.Send(msg);
- }
- // conn is == null when spawning it for the local player
- else
- {
- // send ownerWriter to owner
- // (spawn no matter what, even if no components were
- // serialized because the spawn message contains more data.
- // components might still be updated later on.)
- msg.payload = ownerSegment;
- SendToClientOfPlayer(identity, msg);
-
- // send observersWriter to everyone but owner
- // (spawn no matter what, even if no components were
- // serialized because the spawn message contains more data.
- // components might still be updated later on.)
- msg.payload = observersSegment;
- SendToReady(identity, msg, false);
- }
+ conn.Send(msg);
}
- // 'identity' is a scene object that should be spawned again
- else
+ }
+
+ static ArraySegment CreateSpawnMessagePayload(bool isOwner, NetworkIdentity identity, PooledNetworkWriter ownerWriter, PooledNetworkWriter observersWriter)
+ {
+ // Only call OnSerializeAllSafely if there are NetworkBehaviours
+ if (identity.NetworkBehaviours.Length == 0)
{
- SpawnSceneObjectMessage msg = new SpawnSceneObjectMessage
- {
- netId = identity.netId,
- owner = conn?.identity == identity,
- sceneId = identity.sceneId,
- // use local values for VR support
- position = identity.transform.localPosition,
- rotation = identity.transform.localRotation,
- scale = identity.transform.localScale
- };
+ return default;
+ }
- // conn is != null when spawning it for a client
- if (conn != null)
- {
- // use owner segment if 'conn' owns this identity, otherwise
- // use observers segment
- bool isOwner = identity.connectionToClient == conn;
- msg.payload = isOwner ? ownerSegment : observersSegment;
+ // serialize all components with initialState = true
+ // (can be null if has none)
+ ulong dirtyComponentsMask = identity.GetInitialComponentsMask();
+ identity.OnSerializeAllSafely(true, dirtyComponentsMask, ownerWriter, out int ownerWritten, observersWriter, out int observersWritten);
- conn.Send(msg);
- }
- // conn is == null when spawning it for the local player
- else
- {
- // send ownerWriter to owner
- // (spawn no matter what, even if no components were
- // serialized because the spawn message contains more data.
- // components might still be updated later on.)
- msg.payload = ownerSegment;
- SendToClientOfPlayer(identity, msg);
-
- // send observersWriter to everyone but owner
- // (spawn no matter what, even if no components were
- // serialized because the spawn message contains more data.
- // components might still be updated later on.)
- msg.payload = observersSegment;
- SendToReady(identity, msg, false);
- }
- }
+ // convert to ArraySegment to avoid reader allocations
+ // (need to handle null case too)
+ ArraySegment ownerSegment = ownerWritten > 0 ? ownerWriter.ToArraySegment() : default;
+ ArraySegment observersSegment = observersWritten > 0 ? observersWriter.ToArraySegment() : default;
- NetworkWriterPool.Recycle(ownerWriter);
- NetworkWriterPool.Recycle(observersWriter);
+ // use owner segment if 'conn' owns this identity, otherwise
+ // use observers segment
+ ArraySegment payload = isOwner ? ownerSegment : observersSegment;
+
+ return payload;
}
///
@@ -1209,21 +1114,9 @@ internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnectio
/// The connections object to clean up for.
public static void DestroyPlayerForConnection(NetworkConnection conn)
{
- // => destroy what we can destroy.
- HashSet tmp = new HashSet(conn.clientOwnedObjects);
- foreach (uint netId in tmp)
- {
- if (NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity identity))
- {
- Destroy(identity.gameObject);
- }
- }
-
- if (conn.identity != null)
- {
- DestroyObject(conn.identity, true);
- conn.identity = null;
- }
+ // destroy all objects owned by this connection, including the player object
+ conn.DestroyOwnedObjects();
+ conn.identity = null;
}
///
@@ -1231,38 +1124,13 @@ public static void DestroyPlayerForConnection(NetworkConnection conn)
/// This will cause a new object to be instantiated from the registered prefab, or from a custom spawn function.
///
/// Game object with NetworkIdentity to spawn.
- public static void Spawn(GameObject obj)
+ /// The connection that has authority over the object
+ public static void Spawn(GameObject obj, NetworkConnection ownerConnection = null)
{
if (VerifyCanSpawn(obj))
{
- SpawnObject(obj);
- }
- }
-
- static bool CheckForPrefab(GameObject obj)
- {
-#if UNITY_EDITOR
-#if UNITY_2018_3_OR_NEWER
- return UnityEditor.PrefabUtility.IsPartOfPrefabAsset(obj);
-#elif UNITY_2018_2_OR_NEWER
- return (UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(obj) == null) && (UnityEditor.PrefabUtility.GetPrefabObject(obj) != null);
-#else
- return (UnityEditor.PrefabUtility.GetPrefabParent(obj) == null) && (UnityEditor.PrefabUtility.GetPrefabObject(obj) != null);
-#endif
-#else
- return false;
-#endif
- }
-
- static bool VerifyCanSpawn(GameObject obj)
- {
- if (CheckForPrefab(obj))
- {
- Debug.LogErrorFormat("GameObject {0} is a prefab, it can't be spawned. This will cause errors in builds.", obj.name);
- return false;
+ SpawnObject(obj, ownerConnection);
}
-
- return true;
}
///
@@ -1270,24 +1138,23 @@ static bool VerifyCanSpawn(GameObject obj)
/// This is the same as calling NetworkIdentity.AssignClientAuthority on the spawned object.
///
/// The object to spawn.
- /// The player object to set Client Authority to.
- ///
- public static bool SpawnWithClientAuthority(GameObject obj, GameObject player)
+ /// The player object to set Client Authority to.
+ public static void Spawn(GameObject obj, GameObject ownerPlayer)
{
- NetworkIdentity identity = player.GetComponent();
+ NetworkIdentity identity = ownerPlayer.GetComponent();
if (identity == null)
{
- Debug.LogError("SpawnWithClientAuthority player object has no NetworkIdentity");
- return false;
+ logger.LogError("Player object has no NetworkIdentity");
+ return;
}
if (identity.connectionToClient == null)
{
- Debug.LogError("SpawnWithClientAuthority player object is not a player.");
- return false;
+ logger.LogError("Player object is not a player.");
+ return;
}
- return SpawnWithClientAuthority(obj, identity.connectionToClient);
+ Spawn(obj, identity.connectionToClient);
}
///
@@ -1295,74 +1162,52 @@ public static bool SpawnWithClientAuthority(GameObject obj, GameObject player)
/// This is the same as calling NetworkIdentity.AssignClientAuthority on the spawned object.
///
/// The object to spawn.
- /// The connection to set Client Authority to.
- ///
- public static bool SpawnWithClientAuthority(GameObject obj, NetworkConnection conn)
+ /// The assetId of the object to spawn. Used for custom spawn handlers.
+ /// The connection that has authority over the object
+ public static void Spawn(GameObject obj, Guid assetId, NetworkConnection ownerConnection = null)
{
- if (!conn.isReady)
- {
- Debug.LogError("SpawnWithClientAuthority NetworkConnection is not ready!");
- return false;
- }
-
- Spawn(obj);
-
- NetworkIdentity identity = obj.GetComponent();
- if (identity == null || !identity.isServer)
+ if (VerifyCanSpawn(obj))
{
- // spawning the object failed.
- return false;
+ if (GetNetworkIdentity(obj, out NetworkIdentity identity))
+ {
+ identity.assetId = assetId;
+ }
+ SpawnObject(obj, ownerConnection);
}
-
- return identity.AssignClientAuthority(conn);
}
- ///
- /// This spawns an object like NetworkServer.Spawn() but also assigns Client Authority to the specified client.
- /// This is the same as calling NetworkIdentity.AssignClientAuthority on the spawned object.
- ///
- /// The object to spawn.
- /// The assetId of the object to spawn. Used for custom spawn handlers.
- /// The connection to set Client Authority to.
- ///
- public static bool SpawnWithClientAuthority(GameObject obj, Guid assetId, NetworkConnection conn)
+ static bool CheckForPrefab(GameObject obj)
{
- Spawn(obj, assetId);
-
- NetworkIdentity identity = obj.GetComponent();
- if (identity == null || !identity.isServer)
- {
- // spawning the object failed.
- return false;
- }
-
- return identity.AssignClientAuthority(conn);
+#if UNITY_EDITOR
+#if UNITY_2018_3_OR_NEWER
+ return UnityEditor.PrefabUtility.IsPartOfPrefabAsset(obj);
+#elif UNITY_2018_2_OR_NEWER
+ return (UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(obj) == null) && (UnityEditor.PrefabUtility.GetPrefabObject(obj) != null);
+#else
+ return (UnityEditor.PrefabUtility.GetPrefabParent(obj) == null) && (UnityEditor.PrefabUtility.GetPrefabObject(obj) != null);
+#endif
+#else
+ return false;
+#endif
}
- ///
- /// This spawns an object like NetworkServer.Spawn() but also assigns Client Authority to the specified client.
- /// This is the same as calling NetworkIdentity.AssignClientAuthority on the spawned object.
- ///
- /// The object to spawn.
- /// The assetId of the object to spawn. Used for custom spawn handlers.
- public static void Spawn(GameObject obj, Guid assetId)
+ static bool VerifyCanSpawn(GameObject obj)
{
- if (VerifyCanSpawn(obj))
+ if (CheckForPrefab(obj))
{
- if (GetNetworkIdentity(obj, out NetworkIdentity identity))
- {
- identity.assetId = assetId;
- }
- SpawnObject(obj);
+ logger.LogFormat(LogType.Error, "GameObject {0} is a prefab, it can't be spawned. This will cause errors in builds.", obj.name);
+ return false;
}
+
+ return true;
}
static void DestroyObject(NetworkIdentity identity, bool destroyServerObject)
{
- if (LogFilter.Debug) Debug.Log("DestroyObject instance:" + identity.netId);
+ if (logger.LogEnabled()) logger.Log("DestroyObject instance:" + identity.netId);
NetworkIdentity.spawned.Remove(identity.netId);
- identity.clientAuthorityOwner?.RemoveOwnedObject(identity);
+ identity.connectionToClient?.RemoveOwnedObject(identity);
ObjectDestroyMessage msg = new ObjectDestroyMessage
{
@@ -1373,15 +1218,17 @@ static void DestroyObject(NetworkIdentity identity, bool destroyServerObject)
identity.ClearObservers();
if (NetworkClient.active && localClientActive)
{
- identity.OnNetworkDestroy();
+ identity.OnStopClient();
}
+ identity.OnStopServer();
+
// when unspawning, dont destroy the server's object
if (destroyServerObject)
{
UnityEngine.Object.Destroy(identity.gameObject);
}
- identity.MarkForReset();
+ identity.Reset();
}
///
@@ -1393,7 +1240,7 @@ public static void Destroy(GameObject obj)
{
if (obj == null)
{
- if (LogFilter.Debug) Debug.Log("NetworkServer DestroyObject is null");
+ logger.Log("NetworkServer DestroyObject is null");
return;
}
@@ -1413,7 +1260,7 @@ public static void UnSpawn(GameObject obj)
{
if (obj == null)
{
- if (LogFilter.Debug) Debug.Log("NetworkServer UnspawnObject is null");
+ logger.Log("NetworkServer UnspawnObject is null");
return;
}
@@ -1423,22 +1270,10 @@ public static void UnSpawn(GameObject obj)
}
}
- ///
- /// Obsolete: Use instead.
- ///
- [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Use NetworkIdentity.spawned[netId] instead.")]
- public static GameObject FindLocalObject(uint netId)
- {
- if (NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity identity))
- {
- return identity.gameObject;
- }
- return null;
- }
-
- static bool ValidateSceneObject(NetworkIdentity identity)
+ internal static bool ValidateSceneObject(NetworkIdentity identity)
{
- if (identity.gameObject.hideFlags == HideFlags.NotEditable || identity.gameObject.hideFlags == HideFlags.HideAndDontSave)
+ if (identity.gameObject.hideFlags == HideFlags.NotEditable ||
+ identity.gameObject.hideFlags == HideFlags.HideAndDontSave)
return false;
#if UNITY_EDITOR
@@ -1457,16 +1292,16 @@ static bool ValidateSceneObject(NetworkIdentity identity)
/// Success if objects where spawned.
public static bool SpawnObjects()
{
+ // only if server active
if (!active)
- return true;
+ return false;
NetworkIdentity[] identities = Resources.FindObjectsOfTypeAll();
foreach (NetworkIdentity identity in identities)
{
if (ValidateSceneObject(identity))
{
- if (LogFilter.Debug) Debug.Log("SpawnObjects sceneId:" + identity.sceneId.ToString("X") + " name:" + identity.gameObject.name);
- identity.Reset();
+ if (logger.LogEnabled()) logger.Log("SpawnObjects sceneId:" + identity.sceneId.ToString("X") + " name:" + identity.gameObject.name);
identity.gameObject.SetActive(true);
}
}
@@ -1474,12 +1309,7 @@ public static bool SpawnObjects()
foreach (NetworkIdentity identity in identities)
{
if (ValidateSceneObject(identity))
- {
Spawn(identity.gameObject);
-
- // these objects are server authority - even if "localPlayerAuthority" is set on them
- identity.ForceAuthority(true);
- }
}
return true;
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkStartPosition.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkStartPosition.cs.meta
index 97f5445..ae9ab89 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkStartPosition.cs.meta
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkStartPosition.cs.meta
@@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
- icon: {instanceID: 0}
+ icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkTime.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkTime.cs
index 7ec21dd..7037d54 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkTime.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkTime.cs
@@ -9,6 +9,8 @@ namespace Mirror
///
public static class NetworkTime
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkTime));
+
///
/// how often are we sending ping messages
/// used to calculate network time and RTT
@@ -22,7 +24,6 @@ public static class NetworkTime
static double lastPingTime;
-
// Date and time when the application started
static readonly Stopwatch stopwatch = new Stopwatch();
@@ -67,7 +68,7 @@ internal static void UpdateClient()
// and time from the server
internal static void OnServerPing(NetworkConnection conn, NetworkPingMessage msg)
{
- if (LogFilter.Debug) Debug.Log("OnPingServerMessage conn=" + conn);
+ if (logger.LogEnabled()) logger.Log("OnPingServerMessage conn=" + conn);
NetworkPongMessage pongMsg = new NetworkPongMessage
{
@@ -81,7 +82,7 @@ internal static void OnServerPing(NetworkConnection conn, NetworkPingMessage msg
// Executed at the client when we receive a Pong message
// find out how long it took since we sent the Ping
// and update time offset
- internal static void OnClientPong(NetworkConnection _, NetworkPongMessage msg)
+ internal static void OnClientPong(NetworkPongMessage msg)
{
double now = LocalTime();
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkVisibility.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkVisibility.cs
new file mode 100644
index 0000000..6f30ae6
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkVisibility.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Mirror
+{
+ // the name NetworkProximityCheck implies that it's only about objects in
+ // proximity to the player. But we might have room based, guild based,
+ // instanced based checks too, so NetworkVisibility is more fitting.
+ //
+ // note: we inherit from NetworkBehaviour so we can reuse .netIdentity, etc.
+ // note: unlike UNET, we only allow 1 proximity checker per NetworkIdentity.
+ [DisallowMultipleComponent]
+ public abstract class NetworkVisibility : NetworkBehaviour
+ {
+ ///
+ /// Callback used by the visibility system to determine if an observer (player) can see this object.
+ /// If this function returns true, the network connection will be added as an observer.
+ ///
+ /// Network connection of a player.
+ /// True if the player can see this object.
+ public abstract bool OnCheckObserver(NetworkConnection conn);
+
+ ///
+ /// Callback used by the visibility system to (re)construct the set of observers that can see this object.
+ /// Implementations of this callback should add network connections of players that can see this object to the observers set.
+ ///
+ /// The new set of observers for this object.
+ /// True if the set of observers is being built for the first time.
+ public abstract void OnRebuildObservers(HashSet observers, bool initialize);
+
+ ///
+ /// Callback used by the visibility system for objects on a host.
+ /// Objects on a host (with a local client) cannot be disabled or destroyed when they are not visible to the local client. So this function is called to allow custom code to hide these objects. A typical implementation will disable renderer components on the object. This is only called on local clients on a host.
+ ///
+ /// New visibility state.
+ public virtual void OnSetHostVisibility(bool visible)
+ {
+ foreach (Renderer rend in GetComponentsInChildren())
+ rend.enabled = visible;
+ }
+ }
+}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkVisibility.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkVisibility.cs.meta
new file mode 100644
index 0000000..1e66658
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkVisibility.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c08f1a030234d49d391d7223a8592f15
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkWriter.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkWriter.cs
index a14f66d..05814e9 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkWriter.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkWriter.cs
@@ -1,40 +1,94 @@
using System;
-using System.IO;
+using System.Runtime.CompilerServices;
using System.Text;
using UnityEngine;
namespace Mirror
{
- // Binary stream Writer. Supports simple types, buffers, arrays, structs, and nested types
+ ///
+ /// Binary stream Writer. Supports simple types, buffers, arrays, structs, and nested types
+ /// Use NetworkWriter.GetWriter to reduce memory allocation
+ ///
public class NetworkWriter
{
public const int MaxStringLength = 1024 * 32;
// create writer immediately with it's own buffer so no one can mess with it and so that we can resize it.
// note: BinaryWriter allocates too much, so we only use a MemoryStream
- readonly MemoryStream _stream = new MemoryStream();
- MemoryStream stream
+ // => 1500 bytes by default because on average, most packets will be <= MTU
+ byte[] buffer = new byte[1500];
+
+ // 'int' is the best type for .Position. 'short' is too small if we send >32kb which would result in negative .Position
+ // -> converting long to int is fine until 2GB of data (MAX_INT), so we don't have to worry about overflows here
+ int position;
+ int length;
+
+ public int Length => length;
+
+ public int Position
{
- get
+ get => position;
+ set
{
- validCache = false;
- return _stream;
+ position = value;
+ EnsureLength(value);
}
}
- internal bool validCache;
- byte[] data;
-
- internal bool pooled;
- internal readonly bool reusable;
+ ///
+ /// Reset both the position and length of the stream
+ ///
+ ///
+ /// Leaves the capacity the same so that we can reuse this writer without extra allocations
+ ///
+ public void Reset()
+ {
+ position = 0;
+ length = 0;
+ }
- // 'int' is the best type for .Position. 'short' is too small if we send >32kb which would result in negative .Position
- // -> converting long to int is fine until 2GB of data (MAX_INT), so we don't have to worry about overflows here
- public int Position { get { return (int)stream.Position; } set { stream.Position = value; } }
+ ///
+ /// Sets length, moves position if it is greater than new length
+ ///
+ ///
+ ///
+ /// Zeros out any extra length created by setlength
+ ///
+ public void SetLength(int newLength)
+ {
+ int oldLength = length;
+
+ // ensure length & capacity
+ EnsureLength(newLength);
+
+ // zero out new length
+ if (oldLength < newLength)
+ {
+ Array.Clear(buffer, oldLength, newLength - oldLength);
+ }
+
+ length = newLength;
+ position = Mathf.Min(position, length);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ void EnsureLength(int value)
+ {
+ if (length < value)
+ {
+ length = value;
+ EnsureCapacity(value);
+ }
+ }
- public NetworkWriter(bool reusable = false)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ void EnsureCapacity(int value)
{
- this.reusable = reusable;
+ if (buffer.Length < value)
+ {
+ int capacity = Math.Max(value, buffer.Length * 2);
+ Array.Resize(ref buffer, capacity);
+ }
}
// MemoryStream has 3 values: Position, Length and Capacity.
@@ -44,12 +98,8 @@ public NetworkWriter(bool reusable = false)
// ToArray returns all the data we have written, regardless of the current position
public byte[] ToArray()
{
- if (!validCache)
- {
- stream.Flush();
- data = stream.ToArray();
- validCache = true;
- }
+ byte[] data = new byte[length];
+ Array.ConstrainedCopy(buffer, 0, data, 0, length);
return data;
}
@@ -60,151 +110,50 @@ public byte[] ToArray()
// while you are using the ArraySegment
public ArraySegment ToArraySegment()
{
- stream.Flush();
- if (stream.TryGetBuffer(out ArraySegment data))
- {
- return data;
- }
- throw new Exception("Cannot expose contents of memory stream. Make sure that MemoryStream buffer is publicly visible (see MemoryStream source code).");
+ return new ArraySegment(buffer, 0, length);
}
- // reset both the position and length of the stream, but leaves the capacity the same
- // so that we can reuse this writer without extra allocations
- public void SetLength(long value)
+ public void WriteByte(byte value)
{
- stream.SetLength(value);
+ EnsureLength(position + 1);
+ buffer[position++] = value;
}
- public void WriteByte(byte value) => stream.WriteByte(value);
// for byte arrays with consistent size, where the reader knows how many to read
// (like a packet opcode that's always the same)
public void WriteBytes(byte[] buffer, int offset, int count)
{
- // no null check because we would need to write size info for that too (hence WriteBytesAndSize)
- stream.Write(buffer, offset, count);
+ EnsureLength(position + count);
+ Array.ConstrainedCopy(buffer, offset, this.buffer, position, count);
+ position += count;
}
public void WriteUInt32(uint value)
{
- WriteByte((byte)(value & 0xFF));
- WriteByte((byte)((value >> 8) & 0xFF));
- WriteByte((byte)((value >> 16) & 0xFF));
- WriteByte((byte)((value >> 24) & 0xFF));
+ EnsureLength(position + 4);
+ buffer[position++] = (byte)value;
+ buffer[position++] = (byte)(value >> 8);
+ buffer[position++] = (byte)(value >> 16);
+ buffer[position++] = (byte)(value >> 24);
}
public void WriteInt32(int value) => WriteUInt32((uint)value);
public void WriteUInt64(ulong value)
{
- WriteByte((byte)(value & 0xFF));
- WriteByte((byte)((value >> 8) & 0xFF));
- WriteByte((byte)((value >> 16) & 0xFF));
- WriteByte((byte)((value >> 24) & 0xFF));
- WriteByte((byte)((value >> 32) & 0xFF));
- WriteByte((byte)((value >> 40) & 0xFF));
- WriteByte((byte)((value >> 48) & 0xFF));
- WriteByte((byte)((value >> 56) & 0xFF));
+ EnsureLength(position + 8);
+ buffer[position++] = (byte)value;
+ buffer[position++] = (byte)(value >> 8);
+ buffer[position++] = (byte)(value >> 16);
+ buffer[position++] = (byte)(value >> 24);
+ buffer[position++] = (byte)(value >> 32);
+ buffer[position++] = (byte)(value >> 40);
+ buffer[position++] = (byte)(value >> 48);
+ buffer[position++] = (byte)(value >> 56);
}
public void WriteInt64(long value) => WriteUInt64((ulong)value);
-
- #region Obsoletes
- [Obsolete("Use WriteUInt16 instead")]
- public void Write(ushort value) => this.WriteUInt16(value);
-
- [Obsolete("Use WriteUInt32 instead")]
- public void Write(uint value) => WriteUInt32(value);
-
- [Obsolete("Use WriteUInt64 instead")]
- public void Write(ulong value) => WriteUInt64(value);
-
- [Obsolete("Use WriteByte instead")]
- public void Write(byte value) => stream.WriteByte(value);
-
- [Obsolete("Use WriteSByte instead")]
- public void Write(sbyte value) => WriteByte((byte)value);
-
- // write char the same way that NetworkReader reads it (2 bytes)
- [Obsolete("Use WriteChar instead")]
- public void Write(char value) => this.WriteUInt16((ushort)value);
-
- [Obsolete("Use WriteBoolean instead")]
- public void Write(bool value) => WriteByte((byte)(value ? 1 : 0));
-
- [Obsolete("Use WriteInt16 instead")]
- public void Write(short value) => this.WriteUInt16((ushort)value);
-
- [Obsolete("Use WriteInt32 instead")]
- public void Write(int value) => WriteUInt32((uint)value);
-
- [Obsolete("Use WriteInt64 instead")]
- public void Write(long value) => WriteUInt64((ulong)value);
-
- [Obsolete("Use WriteSingle instead")]
- public void Write(float value) => this.WriteSingle(value);
-
- [Obsolete("Use WriteDouble instead")]
- public void Write(double value) => this.WriteDouble(value);
-
- [Obsolete("Use WriteDecimal instead")]
- public void Write(decimal value) => this.WriteDecimal(value);
-
- [Obsolete("Use WriteString instead")]
- public void Write(string value) => this.WriteString(value);
-
- [Obsolete("Use WriteBytes instead")]
- public void Write(byte[] buffer, int offset, int count) => WriteBytes(buffer, offset, count);
-
- [Obsolete("Use WriteVector2 instead")]
- public void Write(Vector2 value) => this.WriteVector2(value);
-
- [Obsolete("Use WriteVector3 instead")]
- public void Write(Vector3 value) => this.WriteVector3(value);
-
- [Obsolete("Use WriteVector4 instead")]
- public void Write(Vector4 value) => this.WriteVector4(value);
-
- [Obsolete("Use WriteVector2Int instead")]
- public void Write(Vector2Int value) => this.WriteVector2Int(value);
-
- [Obsolete("Use WriteVector3Int instead")]
- public void Write(Vector3Int value) => this.WriteVector3Int(value);
-
- [Obsolete("Use WriteColor instead")]
- public void Write(Color value) => this.WriteColor(value);
-
- [Obsolete("Use WriteColor32 instead")]
- public void Write(Color32 value) => this.WriteColor32(value);
-
- [Obsolete("Use WriteQuaternion instead")]
- public void Write(Quaternion value) => this.WriteQuaternion(value);
-
- [Obsolete("Use WriteRect instead")]
- public void Write(Rect value) => this.WriteRect(value);
-
- [Obsolete("Use WritePlane instead")]
- public void Write(Plane value) => this.WritePlane(value);
-
- [Obsolete("Use WriteRay instead")]
- public void Write(Ray value) => this.WriteRay(value);
-
- [Obsolete("Use WriteMatrix4x4 instead")]
- public void Write(Matrix4x4 value) => this.WriteMatrix4x4(value);
-
- [Obsolete("Use WriteGuid instead")]
- public void Write(Guid value) => this.WriteGuid(value);
-
- [Obsolete("Use WriteNetworkIdentity instead")]
- public void Write(NetworkIdentity value) => this.WriteNetworkIdentity(value);
-
- [Obsolete("Use WriteTransform instead")]
- public void Write(Transform value) => this.WriteTransform(value);
-
- [Obsolete("Use WriteGameObject instead")]
- public void Write(GameObject value) => this.WriteGameObject(value);
-
- #endregion
}
@@ -212,6 +161,8 @@ public void WriteUInt64(ulong value)
// but they do all need to be extensions.
public static class NetworkWriterExtensions
{
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkWriterExtensions));
+
// cache encoding instead of creating it with BinaryWriter each time
// 1000 readers before: 1MB GC, 30ms
// 1000 readers after: 0.8MB GC, 18ms
@@ -222,13 +173,13 @@ public static class NetworkWriterExtensions
public static void WriteSByte(this NetworkWriter writer, sbyte value) => writer.WriteByte((byte)value);
- public static void WriteChar(this NetworkWriter writer, char value) => writer.WriteUInt16((ushort)value);
+ public static void WriteChar(this NetworkWriter writer, char value) => writer.WriteUInt16(value);
public static void WriteBoolean(this NetworkWriter writer, bool value) => writer.WriteByte((byte)(value ? 1 : 0));
public static void WriteUInt16(this NetworkWriter writer, ushort value)
{
- writer.WriteByte((byte)(value & 0xFF));
+ writer.WriteByte((byte)value);
writer.WriteByte((byte)(value >> 8));
}
@@ -271,14 +222,10 @@ public static void WriteString(this NetworkWriter writer, string value)
// (note: original HLAPI would write "" for null strings, but if a
// string is null on the server then it should also be null
// on the client)
- switch (value)
+ if (value == null)
{
- case null:
- writer.WriteUInt16(0);
- return;
- case "":
- writer.WriteUInt16(1);
- return;
+ writer.WriteUInt16(0);
+ return;
}
// write string with same method as NetworkReader
@@ -357,78 +304,78 @@ public static void WritePackedUInt64(this NetworkWriter writer, ulong value)
if (value <= 2287)
{
writer.WriteByte((byte)(((value - 240) >> 8) + 241));
- writer.WriteByte((byte)((value - 240) & 0xFF));
+ writer.WriteByte((byte)(value - 240));
return;
}
if (value <= 67823)
{
- writer.WriteByte((byte)249);
+ writer.WriteByte(249);
writer.WriteByte((byte)((value - 2288) >> 8));
- writer.WriteByte((byte)((value - 2288) & 0xFF));
+ writer.WriteByte((byte)(value - 2288));
return;
}
if (value <= 16777215)
{
- writer.WriteByte((byte)250);
- writer.WriteByte((byte)(value & 0xFF));
- writer.WriteByte((byte)((value >> 8) & 0xFF));
- writer.WriteByte((byte)((value >> 16) & 0xFF));
+ writer.WriteByte(250);
+ writer.WriteByte((byte)value);
+ writer.WriteByte((byte)(value >> 8));
+ writer.WriteByte((byte)(value >> 16));
return;
}
if (value <= 4294967295)
{
- writer.WriteByte((byte)251);
- writer.WriteByte((byte)(value & 0xFF));
- writer.WriteByte((byte)((value >> 8) & 0xFF));
- writer.WriteByte((byte)((value >> 16) & 0xFF));
- writer.WriteByte((byte)((value >> 24) & 0xFF));
+ writer.WriteByte(251);
+ writer.WriteByte((byte)value);
+ writer.WriteByte((byte)(value >> 8));
+ writer.WriteByte((byte)(value >> 16));
+ writer.WriteByte((byte)(value >> 24));
return;
}
if (value <= 1099511627775)
{
- writer.WriteByte((byte)252);
- writer.WriteByte((byte)(value & 0xFF));
- writer.WriteByte((byte)((value >> 8) & 0xFF));
- writer.WriteByte((byte)((value >> 16) & 0xFF));
- writer.WriteByte((byte)((value >> 24) & 0xFF));
- writer.WriteByte((byte)((value >> 32) & 0xFF));
+ writer.WriteByte(252);
+ writer.WriteByte((byte)value);
+ writer.WriteByte((byte)(value >> 8));
+ writer.WriteByte((byte)(value >> 16));
+ writer.WriteByte((byte)(value >> 24));
+ writer.WriteByte((byte)(value >> 32));
return;
}
if (value <= 281474976710655)
{
- writer.WriteByte((byte)253);
- writer.WriteByte((byte)(value & 0xFF));
- writer.WriteByte((byte)((value >> 8) & 0xFF));
- writer.WriteByte((byte)((value >> 16) & 0xFF));
- writer.WriteByte((byte)((value >> 24) & 0xFF));
- writer.WriteByte((byte)((value >> 32) & 0xFF));
- writer.WriteByte((byte)((value >> 40) & 0xFF));
+ writer.WriteByte(253);
+ writer.WriteByte((byte)value);
+ writer.WriteByte((byte)(value >> 8));
+ writer.WriteByte((byte)(value >> 16));
+ writer.WriteByte((byte)(value >> 24));
+ writer.WriteByte((byte)(value >> 32));
+ writer.WriteByte((byte)(value >> 40));
return;
}
if (value <= 72057594037927935)
{
- writer.WriteByte((byte)254);
- writer.WriteByte((byte)(value & 0xFF));
- writer.WriteByte((byte)((value >> 8) & 0xFF));
- writer.WriteByte((byte)((value >> 16) & 0xFF));
- writer.WriteByte((byte)((value >> 24) & 0xFF));
- writer.WriteByte((byte)((value >> 32) & 0xFF));
- writer.WriteByte((byte)((value >> 40) & 0xFF));
- writer.WriteByte((byte)((value >> 48) & 0xFF));
+ writer.WriteByte(254);
+ writer.WriteByte((byte)value);
+ writer.WriteByte((byte)(value >> 8));
+ writer.WriteByte((byte)(value >> 16));
+ writer.WriteByte((byte)(value >> 24));
+ writer.WriteByte((byte)(value >> 32));
+ writer.WriteByte((byte)(value >> 40));
+ writer.WriteByte((byte)(value >> 48));
return;
}
// all others
{
- writer.WriteByte((byte)255);
- writer.WriteByte((byte)(value & 0xFF));
- writer.WriteByte((byte)((value >> 8) & 0xFF));
- writer.WriteByte((byte)((value >> 16) & 0xFF));
- writer.WriteByte((byte)((value >> 24) & 0xFF));
- writer.WriteByte((byte)((value >> 32) & 0xFF));
- writer.WriteByte((byte)((value >> 40) & 0xFF));
- writer.WriteByte((byte)((value >> 48) & 0xFF));
- writer.WriteByte((byte)((value >> 56) & 0xFF));
+ writer.WriteByte(255);
+ writer.WriteByte((byte)value);
+ writer.WriteByte((byte)(value >> 8));
+ writer.WriteByte((byte)(value >> 16));
+ writer.WriteByte((byte)(value >> 24));
+ writer.WriteByte((byte)(value >> 32));
+ writer.WriteByte((byte)(value >> 40));
+ writer.WriteByte((byte)(value >> 48));
+ writer.WriteByte((byte)(value >> 56));
}
}
@@ -548,7 +495,7 @@ public static void WriteNetworkIdentity(this NetworkWriter writer, NetworkIdenti
public static void WriteTransform(this NetworkWriter writer, Transform value)
{
- if (value == null || value.gameObject == null)
+ if (value == null)
{
writer.WritePackedUInt32(0);
return;
@@ -560,7 +507,7 @@ public static void WriteTransform(this NetworkWriter writer, Transform value)
}
else
{
- Debug.LogWarning("NetworkWriter " + value + " has no NetworkIdentity");
+ logger.LogWarning("NetworkWriter " + value + " has no NetworkIdentity");
writer.WritePackedUInt32(0);
}
}
@@ -579,12 +526,17 @@ public static void WriteGameObject(this NetworkWriter writer, GameObject value)
}
else
{
- Debug.LogWarning("NetworkWriter " + value + " has no NetworkIdentity");
+ logger.LogWarning("NetworkWriter " + value + " has no NetworkIdentity");
writer.WritePackedUInt32(0);
}
}
- public static void Write(this NetworkWriter writer, T msg) where T : IMessageBase
+ public static void WriteUri(this NetworkWriter writer, Uri uri)
+ {
+ writer.WriteString(uri.ToString());
+ }
+
+ public static void WriteMessage(this NetworkWriter writer, T msg) where T : IMessageBase
{
msg.Serialize(writer);
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkWriterPool.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkWriterPool.cs
index 97db231..79a6ab1 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkWriterPool.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/NetworkWriterPool.cs
@@ -1,38 +1,97 @@
-using System.Collections.Generic;
+using System;
using UnityEngine;
namespace Mirror
{
+ ///
+ /// NetworkWriter to be used with NetworkWriterPool
+ ///
+ public class PooledNetworkWriter : NetworkWriter, IDisposable
+ {
+ public void Dispose()
+ {
+ NetworkWriterPool.Recycle(this);
+ }
+ }
+
+ ///
+ /// Pool of NetworkWriters
+ /// Use this pool instead of NetworkWriter to reduce memory allocation
+ /// Use Capacity to change size of pool
+ ///
public static class NetworkWriterPool
{
- static readonly Stack pool = new Stack();
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkWriterPool), LogType.Error);
+
+ ///
+ /// Size of the pool
+ /// If pool is too small getting writers will causes memory allocation
+ /// Default value: 100
+ ///
+ public static int Capacity
+ {
+ get => pool.Length;
+ set
+ {
+ // resize the array
+ Array.Resize(ref pool, value);
+
+ // if capacity is smaller than before, then we need to adjust
+ // 'next' so it doesn't point to an index out of range
+ // -> if we set '0' then next = min(_, 0-1) => -1
+ // -> if we set '2' then next = min(_, 2-1) => 1
+ next = Mathf.Min(next, pool.Length - 1);
+ }
+ }
- public static NetworkWriter GetWriter()
+ ///
+ /// Mirror usually only uses up to 4 writes in nested usings,
+ /// 100 is a good margin for edge cases when users need a lot writers at
+ /// the same time.
+ ///
+ /// keep in mind, most entries of the pool will be null in most cases
+ ///
+ ///
+ /// Note: we use an Array instead of a Stack because it's significantly
+ /// faster: https://github.com/vis2k/Mirror/issues/1614
+ static PooledNetworkWriter[] pool = new PooledNetworkWriter[100];
+
+ static int next = -1;
+
+ ///
+ /// Get the next writer in the pool
+ /// If pool is empty, creates a new Writer
+ ///
+ public static PooledNetworkWriter GetWriter()
{
- if (pool.Count != 0)
+ if (next == -1)
{
- NetworkWriter writer = pool.Pop();
- // reset cached writer length and position
- writer.pooled = false;
- writer.SetLength(0);
- return writer;
+ return new PooledNetworkWriter();
}
- return new NetworkWriter(true);
+ PooledNetworkWriter writer = pool[next];
+ pool[next] = null;
+ next--;
+
+ // reset cached writer length and position
+ writer.Reset();
+ return writer;
}
- public static void Recycle(NetworkWriter writer)
+ ///
+ /// Puts writer back into pool
+ /// When pool is full, the extra writer is left for the GC
+ ///
+ public static void Recycle(PooledNetworkWriter writer)
{
- if (writer == null)
+ if (next < pool.Length - 1)
{
- Debug.LogWarning("Recycling null writers is not allowed, please check your code!");
- return;
+ next++;
+ pool[next] = writer;
}
- if (writer.reusable && !writer.pooled)
+ else
{
- writer.pooled = true;
- writer.validCache = false;
- pool.Push(writer);
+ logger.LogWarning("NetworkWriterPool.Recycle, Pool was full leaving extra writer for GC");
}
}
}
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/RemoteCallHelper.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/RemoteCallHelper.cs
new file mode 100644
index 0000000..f89f83b
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/RemoteCallHelper.cs
@@ -0,0 +1,200 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Mirror.RemoteCalls
+{
+ ///
+ /// Delegate for Command functions.
+ ///
+ ///
+ ///
+ public delegate void CmdDelegate(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection);
+
+ class Invoker
+ {
+ public Type invokeClass;
+ public MirrorInvokeType invokeType;
+ public CmdDelegate invokeFunction;
+ public bool cmdIgnoreAuthority;
+
+ public bool AreEqual(Type invokeClass, MirrorInvokeType invokeType, CmdDelegate invokeFunction)
+ {
+ return (this.invokeClass == invokeClass &&
+ this.invokeType == invokeType &&
+ this.invokeFunction == invokeFunction);
+ }
+ }
+
+ public struct CommandInfo
+ {
+ public bool ignoreAuthority;
+ }
+
+ ///
+ /// Used to help manage remote calls for NetworkBehaviours
+ ///
+ public static class RemoteCallHelper
+ {
+ static readonly ILogger logger = LogFactory.GetLogger(typeof(RemoteCallHelper));
+
+ static readonly Dictionary cmdHandlerDelegates = new Dictionary();
+
+ ///
+ /// Creates hash from Type and method name
+ ///
+ ///
+ ///
+ ///
+ internal static int GetMethodHash(Type invokeClass, string methodName)
+ {
+ // (invokeClass + ":" + cmdName).GetStableHashCode() would cause allocations.
+ // so hash1 + hash2 is better.
+ unchecked
+ {
+ int hash = invokeClass.FullName.GetStableHashCode();
+ return hash * 503 + methodName.GetStableHashCode();
+ }
+ }
+
+
+ ///
+ /// helper function register a Command/Rpc/SyncEvent delegate
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// remote function hash
+ internal static int RegisterDelegate(Type invokeClass, string cmdName, MirrorInvokeType invokerType, CmdDelegate func, bool cmdIgnoreAuthority = false)
+ {
+ // type+func so Inventory.RpcUse != Equipment.RpcUse
+ int cmdHash = GetMethodHash(invokeClass, cmdName);
+
+ if (CheckIfDeligateExists(invokeClass, invokerType, func, cmdHash))
+ return cmdHash;
+
+ Invoker invoker = new Invoker
+ {
+ invokeType = invokerType,
+ invokeClass = invokeClass,
+ invokeFunction = func,
+ cmdIgnoreAuthority = cmdIgnoreAuthority,
+ };
+
+ cmdHandlerDelegates[cmdHash] = invoker;
+
+ if (logger.LogEnabled())
+ {
+ string ingoreAuthorityMessage = invokerType == MirrorInvokeType.Command ? $" IgnoreAuthority:{cmdIgnoreAuthority}" : "";
+ logger.Log($"RegisterDelegate hash: {cmdHash} invokerType: {invokerType} method: {func.GetMethodName()}{ingoreAuthorityMessage}");
+ }
+
+ return cmdHash;
+ }
+
+ static bool CheckIfDeligateExists(Type invokeClass, MirrorInvokeType invokerType, CmdDelegate func, int cmdHash)
+ {
+ if (cmdHandlerDelegates.ContainsKey(cmdHash))
+ {
+ // something already registered this hash
+ Invoker oldInvoker = cmdHandlerDelegates[cmdHash];
+ if (oldInvoker.AreEqual(invokeClass, invokerType, func))
+ {
+ // it's all right, it was the same function
+ return true;
+ }
+
+ logger.LogError($"Function {oldInvoker.invokeClass}.{oldInvoker.invokeFunction.GetMethodName()} and {invokeClass}.{func.GetMethodName()} have the same hash. Please rename one of them");
+ }
+
+ return false;
+ }
+
+ public static void RegisterCommandDelegate(Type invokeClass, string cmdName, CmdDelegate func, bool ignoreAuthority)
+ {
+ RegisterDelegate(invokeClass, cmdName, MirrorInvokeType.Command, func, ignoreAuthority);
+ }
+
+ public static void RegisterRpcDelegate(Type invokeClass, string rpcName, CmdDelegate func)
+ {
+ RegisterDelegate(invokeClass, rpcName, MirrorInvokeType.ClientRpc, func);
+ }
+
+ public static void RegisterEventDelegate(Type invokeClass, string eventName, CmdDelegate func)
+ {
+ RegisterDelegate(invokeClass, eventName, MirrorInvokeType.SyncEvent, func);
+ }
+
+ // we need a way to clean up delegates after tests
+ [System.Obsolete("Removing all delegates will cause problems with other tests as their hashs can not be re-added without reloading scripts", true)]
+ internal static void ClearDelegates()
+ {
+ cmdHandlerDelegates.Clear();
+ }
+
+ ///
+ /// We need this in order to clean up tests
+ ///
+ internal static void RemoveDelegate(int hash)
+ {
+ cmdHandlerDelegates.Remove(hash);
+ }
+
+ static bool GetInvokerForHash(int cmdHash, MirrorInvokeType invokeType, out Invoker invoker)
+ {
+ if (cmdHandlerDelegates.TryGetValue(cmdHash, out invoker) && invoker != null && invoker.invokeType == invokeType)
+ {
+ return true;
+ }
+
+ // debug message if not found, or null, or mismatched type
+ // (no need to throw an error, an attacker might just be trying to
+ // call an cmd with an rpc's hash)
+ if (logger.LogEnabled()) logger.Log("GetInvokerForHash hash:" + cmdHash + " not found");
+
+ return false;
+ }
+
+ // InvokeCmd/Rpc/SyncEventDelegate can all use the same function here
+ internal static bool InvokeHandlerDelegate(int cmdHash, MirrorInvokeType invokeType, NetworkReader reader, NetworkBehaviour invokingType, NetworkConnectionToClient senderConnection = null)
+ {
+ if (GetInvokerForHash(cmdHash, invokeType, out Invoker invoker) && invoker.invokeClass.IsInstanceOfType(invokingType))
+ {
+ invoker.invokeFunction(invokingType, reader, senderConnection);
+
+ return true;
+ }
+ return false;
+ }
+
+ internal static CommandInfo GetCommandInfo(int cmdHash, NetworkBehaviour invokingType)
+ {
+ if (GetInvokerForHash(cmdHash, MirrorInvokeType.Command, out Invoker invoker) && invoker.invokeClass.IsInstanceOfType(invokingType))
+ {
+ return new CommandInfo
+ {
+ ignoreAuthority = invoker.cmdIgnoreAuthority
+ };
+ }
+ return default;
+ }
+
+ ///
+ /// Gets the handler function for a given hash
+ /// Can be used by profilers and debuggers
+ ///
+ /// rpc function hash
+ /// The function delegate that will handle the command
+ public static CmdDelegate GetDelegate(int cmdHash)
+ {
+ if (cmdHandlerDelegates.TryGetValue(cmdHash, out Invoker invoker))
+ {
+ return invoker.invokeFunction;
+ }
+ return null;
+ }
+ }
+}
+
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/RemoteCallHelper.cs.meta b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/RemoteCallHelper.cs.meta
new file mode 100644
index 0000000..862d6e4
--- /dev/null
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/RemoteCallHelper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d2cdbcbd1e377d6408a91acbec31ba16
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/SyncDictionary.cs b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/SyncDictionary.cs
index a5a9d18..32f4639 100644
--- a/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/SyncDictionary.cs
+++ b/LiteNetLib4Mirror/Assets/MirrorLib/Mirror/Runtime/SyncDictionary.cs
@@ -1,15 +1,16 @@
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
+using JetBrains.Annotations;
namespace Mirror
{
[EditorBrowsable(EditorBrowsableState.Never)]
- public abstract class SyncDictionary : IDictionary, SyncObject
+ public abstract class SyncIDictionary : IDictionary, SyncObject, IReadOnlyDictionary
{
public delegate void SyncDictionaryChanged(Operation op, TKey key, TValue item);
- readonly IDictionary objects;
+ protected readonly IDictionary objects;
public int Count => objects.Count;
public bool IsReadOnly { get; private set; }
@@ -20,8 +21,7 @@ public enum Operation : byte
OP_ADD,
OP_CLEAR,
OP_REMOVE,
- OP_SET,
- OP_DIRTY
+ OP_SET
}
struct Change
@@ -38,6 +38,14 @@ struct Change
// so we need to skip them
int changesAhead;
+ public void Reset()
+ {
+ IsReadOnly = false;
+ changes.Clear();
+ changesAhead = 0;
+ objects.Clear();
+ }
+
protected virtual void SerializeKey(NetworkWriter writer, TKey item) { }
protected virtual void SerializeItem(NetworkWriter writer, TValue item) { }
protected virtual TKey DeserializeKey(NetworkReader reader) => default;
@@ -49,21 +57,15 @@ protected virtual void SerializeItem(NetworkWriter writer, TValue item) { }
public ICollection Values => objects.Values;
+ IEnumerable IReadOnlyDictionary.Keys => objects.Keys;
+
+ IEnumerable IReadOnlyDictionary.Values => objects.Values;
+
// throw away all the changes
// this should be called after a successfull sync
public void Flush() => changes.Clear();
- protected SyncDictionary()
- {
- objects = new Dictionary();
- }
-
- protected SyncDictionary(IEqualityComparer eq)
- {
- objects = new Dictionary(eq);
- }
-
- protected SyncDictionary(IDictionary objects)
+ protected SyncIDictionary(IDictionary objects)
{
this.objects = objects;
}
@@ -120,7 +122,6 @@ public void OnSerializeDelta(NetworkWriter writer)
case Operation.OP_ADD:
case Operation.OP_REMOVE:
case Operation.OP_SET:
- case Operation.OP_DIRTY:
SerializeKey(writer, change.key);
SerializeItem(writer, change.item);
break;
@@ -175,7 +176,6 @@ public void OnDeserializeDelta(NetworkReader reader)
{
case Operation.OP_ADD:
case Operation.OP_SET:
- case Operation.OP_DIRTY:
key = DeserializeKey(reader);
item = DeserializeItem(reader);
if (apply)
@@ -231,18 +231,21 @@ public bool Remove(TKey key)
return false;
}
- public void Dirty(TKey index)
- {
- AddOperation(Operation.OP_DIRTY, index, objects[index]);
- }
-
public TValue this[TKey i]
{
get => objects[i];
set
{
- AddOperation(ContainsKey(i) ? Operation.OP_SET : Operation.OP_ADD, i, value);
- objects[i] = value;
+ if (ContainsKey(i))
+ {
+ objects[i] = value;
+ AddOperation(Operation.OP_SET, i, value);
+ }
+ else
+ {
+ objects[i] = value;
+ AddOperation(Operation.OP_ADD, i, value);
+ }
}
}
@@ -261,12 +264,8 @@ public bool Contains(KeyValuePair item)
return TryGetValue(item.Key, out TValue val) && EqualityComparer.Default.Equals(val, item.Value);
}
- public void CopyTo(KeyValuePair[] array, int arrayIndex)
+ public void CopyTo([NotNull] KeyValuePair[] array, int arrayIndex)
{
- if (array == null)
- {
- throw new System.ArgumentNullException(nameof(array), "Array Is Null");
- }
if (arrayIndex < 0 || arrayIndex > array.Length)
{
throw new System.ArgumentOutOfRangeException(nameof(arrayIndex), "Array Index Out of Range");
@@ -298,4 +297,22 @@ public bool Remove(KeyValuePair item)
IEnumerator IEnumerable.GetEnumerator() => objects.GetEnumerator();
}
+
+ public abstract class SyncDictionary : SyncIDictionary
+ {
+ protected SyncDictionary() : base(new Dictionary())
+ {
+ }
+
+ protected SyncDictionary(IEqualityComparer eq) : base(new Dictionary(eq))
+ {
+ }
+
+ public new Dictionary.ValueCollection Values => ((Dictionary