初始化

This commit is contained in:
come
2025-07-26 16:56:42 +08:00
parent 8291dbb91c
commit fa81439a8c
2574 changed files with 328492 additions and 2170 deletions

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 42130aa0870f6df4bb6217cc2e5805c3
guid: 217bb07fcea56ab42b8e338a8d59c9a7
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,99 @@
using UnityEngine;
using System;
#if UNITY_EDITOR
using System.Reflection;
#endif
public static class ConsoleProDebug
{
// Clear the console and the native console
public static void Clear()
{
#if UNITY_EDITOR
if(ConsoleClearMethod != null)
{
ConsoleClearMethod.Invoke(null, null);
}
#endif
}
// Send a log to a specific filter regardless of contents
// Ex: ConsoleProDebug.LogToFilter("Hi", "CustomFilter");
public static void LogToFilter(string inLog, string inFilterName, UnityEngine.Object inContext = null)
{
Debug.Log(inLog + "\nCPAPI:{\"cmd\":\"Filter\", \"name\":\"" + inFilterName + "\"}", inContext);
}
// Send a log as a regular log but change its type in ConsolePro
// Ex: ConsoleProDebug.LogAsType("Hi", "Error");
public static void LogAsType(string inLog, string inTypeName, UnityEngine.Object inContext = null)
{
Debug.Log(inLog + "\nCPAPI:{\"cmd\":\"LogType\", \"name\":\"" + inTypeName + "\"}", inContext);
}
// Watch a variable. This will only produce one log entry regardless of how many times it is logged, allowing you to track variables without spam.
// Ex:
// void Update() {
// ConsoleProDebug.Watch("Player X Position", transform.position.x);
// }
public static void Watch(string inName, string inValue)
{
Debug.Log(inName + " : " + inValue + "\nCPAPI:{\"cmd\":\"Watch\", \"name\":\"" + inName + "\"}");
}
public static void Search(string inText)
{
Debug.Log("\nCPAPI:{\"cmd\":\"Search\", \"text\":\"" + inText + "\"}");
}
#if UNITY_EDITOR
// Reflection calls to access Console Pro from runtime
private static bool _checkedConsoleClearMethod = false;
private static MethodInfo _consoleClearMethod = null;
private static MethodInfo ConsoleClearMethod
{
get
{
if(_consoleClearMethod == null || !_checkedConsoleClearMethod)
{
_checkedConsoleClearMethod = true;
if(ConsoleWindowType == null)
{
return null;
}
_consoleClearMethod = ConsoleWindowType.GetMethod("ClearEntries", BindingFlags.Static | BindingFlags.Public);
}
return _consoleClearMethod;
}
}
private static bool _checkedConsoleWindowType = false;
private static Type _consoleWindowType = null;
private static Type ConsoleWindowType
{
get
{
if(_consoleWindowType == null || !_checkedConsoleWindowType)
{
_checkedConsoleWindowType = true;
Assembly[] assemblies = System.AppDomain.CurrentDomain.GetAssemblies();
for(int iAssembly = 0; iAssembly < assemblies.Length; iAssembly++)
{
Type[] types = assemblies[iAssembly].GetTypes();
for(int iType = 0; iType < types.Length; iType++)
{
if(types[iType].Name == "ConsolePro3Window")
{
_consoleWindowType = types[iType];
}
}
}
}
return _consoleWindowType;
}
}
#endif
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 30f42e8a12eb842acbe9a63057fb00e4
timeCreated: 1469329295
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5de782a9528f04b41a8ba70afba32a61
timeCreated: 1498113024
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4bb9fa3b2a6b341a9af20d3b5f03ee13
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: a2284c517ee274c19a6ba4c1a8c96fb6
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3f14d07c8a9074483a59436a3caaad09
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,249 @@
// Uncomment to use in Editor
#define USECONSOLEPROREMOTESERVERINEDITOR
// #if (UNITY_WP_8_1 || UNITY_WSA)
// #define UNSUPPORTEDCONSOLEPROREMOTESERVER
// #endif
#if (!UNITY_EDITOR && DEBUG) || (UNITY_EDITOR && USECONSOLEPROREMOTESERVERINEDITOR)
#if !UNSUPPORTEDCONSOLEPROREMOTESERVER
#define USECONSOLEPROREMOTESERVER
#endif
#endif
#if UNITY_EDITOR && !USECONSOLEPROREMOTESERVER
#elif UNSUPPORTEDCONSOLEPROREMOTESERVER
#elif !USECONSOLEPROREMOTESERVER
#else
using System;
using System.Collections.Generic;
#endif
using System.Net;
using System.Net.Sockets;
using UnityEngine;
#if USECONSOLEPROREMOTESERVER
using FlyingWormConsole3.LiteNetLib;
using FlyingWormConsole3.LiteNetLib.Utils;
#endif
namespace FlyingWormConsole3
{
#if USECONSOLEPROREMOTESERVER
public class ConsoleProRemoteServer : MonoBehaviour, INetEventListener
#else
public class ConsoleProRemoteServer : MonoBehaviour
#endif
{
public bool useNATPunch = false;
public int port = 51000;
#if UNITY_EDITOR && !USECONSOLEPROREMOTESERVER
#elif UNSUPPORTEDCONSOLEPROREMOTESERVER
public void Awake()
{
Debug.Log("Console Pro Remote Server is not supported on this platform");
}
#elif !USECONSOLEPROREMOTESERVER
public void Awake()
{
Debug.Log("Console Pro Remote Server is disabled in release mode, please use a Development build or define DEBUG to use it");
}
#else
private NetManager _netServer;
private NetPeer _ourPeer;
private NetDataWriter _dataWriter;
[System.SerializableAttribute]
public class QueuedLog
{
public string timestamp;
public string message;
public string logType;
}
[NonSerializedAttribute]
public List<QueuedLog> logs = new List<QueuedLog>();
private static ConsoleProRemoteServer instance = null;
void Awake()
{
if(instance != null)
{
Destroy(gameObject);
}
instance = this;
DontDestroyOnLoad(gameObject);
Debug.Log("#Remote# Starting Console Pro Server on port : " + port);
_dataWriter = new NetDataWriter();
_netServer = new NetManager(this);
_netServer.Start(port);
_netServer.BroadcastReceiveEnabled = true;
_netServer.UpdateTime = 15;
_netServer.NatPunchEnabled = useNATPunch;
}
void OnDestroy()
{
if(_netServer != null)
{
_netServer.Stop();
}
}
public void OnPeerConnected(NetPeer peer)
{
Debug.Log("#Remote# Connected to " + peer.EndPoint);
_ourPeer = peer;
}
public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo)
{
Debug.Log("#Remote# Disconnected from " + peer.EndPoint + ", info: " + disconnectInfo.Reason);
if (peer == _ourPeer)
{
_ourPeer = null;
}
}
public void OnNetworkError(IPEndPoint endPoint, SocketError socketError)
{
// throw new NotImplementedException();
}
public void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod)
{
// throw new NotImplementedException();
}
public void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType)
{
if(messageType == UnconnectedMessageType.Broadcast)
{
// Debug.Log("#Remote# Received discovery request. Send discovery response");
_netServer.SendUnconnectedMessage(new byte[] {1}, remoteEndPoint);
}
}
public void OnPeerDisconnected(NetPeer peer, DisconnectReason reason, int socketErrorCode)
{
}
public void OnNetworkLatencyUpdate(NetPeer peer, int latency)
{
}
public void OnConnectionRequest(ConnectionRequest request)
{
// Debug.Log("#Remote# Connection requested, accepting");
request.AcceptIfKey("Console Pro");
}
#if UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_4_8 || UNITY_4_9
void OnEnable()
{
Application.RegisterLogCallback(LogCallback);
}
void Update()
{
Application.RegisterLogCallback(LogCallback);
}
void OnDisable()
{
Application.RegisterLogCallback(null);
}
#else
void OnEnable()
{
Application.logMessageReceivedThreaded += LogCallback;
}
void OnDisable()
{
Application.logMessageReceivedThreaded -= LogCallback;
}
#endif
public void LogCallback(string logString, string stackTrace, LogType type)
{
if(!logString.StartsWith("CPIGNORE"))
{
QueueLog(logString, stackTrace, type);
}
}
void QueueLog(string logString, string stackTrace, LogType type)
{
if(logs.Count > 1000)
{
while(logs.Count > 1000)
{
logs.RemoveAt(0);
}
}
#if CSHARP_7_3_OR_NEWER
logString = $"{logString}\n{stackTrace}\n";
logs.Add(new QueuedLog() { message = logString, logType = type.ToString(), timestamp = $"[{DateTime.Now.ToString("HH:mm:ss")}]" } );
#else
logString = logString + "\n" + stackTrace + "\n";
logs.Add(new QueuedLog() { message = logString, logType = type.ToString(), timestamp = "[" + DateTime.Now.ToString("HH:mm:ss") + "]" } );
#endif
}
void LateUpdate()
{
if(_netServer == null)
{
return;
}
_netServer.PollEvents();
if(_ourPeer == null)
{
return;
}
if(logs.Count <= 0)
{
return;
}
string cMessage = "";
foreach(var cLog in logs)
{
cMessage = JsonUtility.ToJson(cLog);
_dataWriter.Reset();
_dataWriter.Put(cMessage);
_ourPeer.Send(_dataWriter, DeliveryMethod.ReliableOrdered);
}
logs.Clear();
}
#endif
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d6bcfaced529e418bb75980b297fda2a
timeCreated: 1437614101
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2c6bd635eeaa04c228b6d342c4758ad7
folderAsset: yes
timeCreated: 1494014730
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,52 @@
using System.Collections.Generic;
using System.Threading;
namespace FlyingWormConsole3.LiteNetLib
{
internal abstract class BaseChannel
{
protected readonly NetPeer Peer;
protected readonly Queue<NetPacket> OutgoingQueue;
private int _isAddedToPeerChannelSendQueue;
public int PacketsInQueue
{
get { return OutgoingQueue.Count; }
}
protected BaseChannel(NetPeer peer)
{
Peer = peer;
OutgoingQueue = new Queue<NetPacket>(64);
}
public void AddToQueue(NetPacket packet)
{
lock (OutgoingQueue)
{
OutgoingQueue.Enqueue(packet);
}
AddToPeerChannelSendQueue();
}
protected void AddToPeerChannelSendQueue()
{
if (Interlocked.CompareExchange(ref _isAddedToPeerChannelSendQueue, 1, 0) == 0)
{
Peer.AddToReliableChannelSendQueue(this);
}
}
public bool SendAndCheckQueue()
{
bool hasPacketsToSend = SendNextPackets();
if (!hasPacketsToSend)
Interlocked.Exchange(ref _isAddedToPeerChannelSendQueue, 0);
return hasPacketsToSend;
}
protected abstract bool SendNextPackets();
public abstract bool ProcessPacket(NetPacket packet);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 763566e7d03d94946afed98596540971
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
using System.Net;
using System.Threading;
using FlyingWormConsole3.LiteNetLib.Utils;
namespace FlyingWormConsole3.LiteNetLib
{
internal enum ConnectionRequestResult
{
None,
Accept,
Reject,
RejectForce
}
public class ConnectionRequest
{
private readonly NetManager _listener;
private int _used;
public readonly NetDataReader Data;
internal ConnectionRequestResult Result { get; private set; }
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,
NetDataReader netDataReader,
IPEndPoint endPoint,
NetManager listener)
{
ConnectionTime = connectionId;
ConnectionNumber = connectionNumber;
RemoteEndPoint = endPoint;
Data = netDataReader;
_listener = listener;
}
public NetPeer AcceptIfKey(string key)
{
if (!TryActivate())
return null;
try
{
if (Data.GetString() == key)
Result = ConnectionRequestResult.Accept;
}
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;
}
/// <summary>
/// Accept connection and get new NetPeer as result
/// </summary>
/// <returns>Connected NetPeer</returns>
public NetPeer Accept()
{
if (!TryActivate())
return null;
Result = ConnectionRequestResult.Accept;
return _listener.OnConnectionSolved(this, null, 0, 0);
}
public void Reject(byte[] rejectData, int start, int length, bool force)
{
if (!TryActivate())
return;
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, false);
}
public void Reject(byte[] rejectData)
{
Reject(rejectData, 0, rejectData.Length, false);
}
public void Reject(NetDataWriter rejectData)
{
Reject(rejectData.Data, 0, rejectData.Length, false);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 01553ccc867ec43bbb1ae69d3de1ddda
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,247 @@
using System.Net;
using System.Net.Sockets;
using FlyingWormConsole3.LiteNetLib.Utils;
namespace FlyingWormConsole3.LiteNetLib
{
/// <summary>
/// Type of message that you receive in OnNetworkReceiveUnconnected event
/// </summary>
public enum UnconnectedMessageType
{
BasicMessage,
Broadcast
}
/// <summary>
/// Disconnect reason that you receive in OnPeerDisconnected event
/// </summary>
public enum DisconnectReason
{
ConnectionFailed,
Timeout,
HostUnreachable,
NetworkUnreachable,
RemoteConnectionClose,
DisconnectPeerCalled,
ConnectionRejected,
InvalidProtocol,
UnknownHost,
Reconnect,
PeerToPeerConnection
}
/// <summary>
/// Additional information about disconnection
/// </summary>
public struct DisconnectInfo
{
/// <summary>
/// Additional info why peer disconnected
/// </summary>
public DisconnectReason Reason;
/// <summary>
/// Error code (if reason is SocketSendError or SocketReceiveError)
/// </summary>
public SocketError SocketErrorCode;
/// <summary>
/// Additional data that can be accessed (only if reason is RemoteConnectionClose)
/// </summary>
public NetPacketReader AdditionalData;
}
public interface INetEventListener
{
/// <summary>
/// New remote peer connected to host, or client connected to remote host
/// </summary>
/// <param name="peer">Connected peer object</param>
void OnPeerConnected(NetPeer peer);
/// <summary>
/// Peer disconnected
/// </summary>
/// <param name="peer">disconnected peer</param>
/// <param name="disconnectInfo">additional info about reason, errorCode or data received with disconnect message</param>
void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo);
/// <summary>
/// Network error (on send or receive)
/// </summary>
/// <param name="endPoint">From endPoint (can be null)</param>
/// <param name="socketError">Socket error</param>
void OnNetworkError(IPEndPoint endPoint, SocketError socketError);
/// <summary>
/// Received some data
/// </summary>
/// <param name="peer">From peer</param>
/// <param name="reader">DataReader containing all received data</param>
/// <param name="deliveryMethod">Type of received packet</param>
void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod);
/// <summary>
/// Received unconnected message
/// </summary>
/// <param name="remoteEndPoint">From address (IP and Port)</param>
/// <param name="reader">Message data</param>
/// <param name="messageType">Message type (simple, discovery request or response)</param>
void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType);
/// <summary>
/// Latency information updated
/// </summary>
/// <param name="peer">Peer with updated latency</param>
/// <param name="latency">latency value in milliseconds</param>
void OnNetworkLatencyUpdate(NetPeer peer, int latency);
/// <summary>
/// On peer connection requested
/// </summary>
/// <param name="request">Request information (EndPoint, internal id, additional data)</param>
void OnConnectionRequest(ConnectionRequest request);
}
public interface IDeliveryEventListener
{
/// <summary>
/// On reliable message delivered
/// </summary>
/// <param name="peer"></param>
/// <param name="userData"></param>
void OnMessageDelivered(NetPeer peer, object userData);
}
public interface INtpEventListener
{
/// <summary>
/// Ntp response
/// </summary>
/// <param name="packet"></param>
void OnNtpResponse(NtpPacket packet);
}
public class EventBasedNetListener : INetEventListener, IDeliveryEventListener, INtpEventListener
{
public delegate void OnPeerConnected(NetPeer peer);
public delegate void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo);
public delegate void OnNetworkError(IPEndPoint endPoint, SocketError socketError);
public delegate void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod);
public delegate void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType);
public delegate void OnNetworkLatencyUpdate(NetPeer peer, int latency);
public delegate void OnConnectionRequest(ConnectionRequest request);
public delegate void OnDeliveryEvent(NetPeer peer, object userData);
public delegate void OnNtpResponseEvent(NtpPacket packet);
public event OnPeerConnected PeerConnectedEvent;
public event OnPeerDisconnected PeerDisconnectedEvent;
public event OnNetworkError NetworkErrorEvent;
public event OnNetworkReceive NetworkReceiveEvent;
public event OnNetworkReceiveUnconnected NetworkReceiveUnconnectedEvent;
public event OnNetworkLatencyUpdate NetworkLatencyUpdateEvent;
public event OnConnectionRequest ConnectionRequestEvent;
public event OnDeliveryEvent DeliveryEvent;
public event OnNtpResponseEvent NtpResponseEvent;
public void ClearPeerConnectedEvent()
{
PeerConnectedEvent = null;
}
public void ClearPeerDisconnectedEvent()
{
PeerDisconnectedEvent = null;
}
public void ClearNetworkErrorEvent()
{
NetworkErrorEvent = null;
}
public void ClearNetworkReceiveEvent()
{
NetworkReceiveEvent = null;
}
public void ClearNetworkReceiveUnconnectedEvent()
{
NetworkReceiveUnconnectedEvent = null;
}
public void ClearNetworkLatencyUpdateEvent()
{
NetworkLatencyUpdateEvent = null;
}
public void ClearConnectionRequestEvent()
{
ConnectionRequestEvent = null;
}
public void ClearDeliveryEvent()
{
DeliveryEvent = null;
}
public void ClearNtpResponseEvent()
{
NtpResponseEvent = null;
}
void INetEventListener.OnPeerConnected(NetPeer peer)
{
if (PeerConnectedEvent != null)
PeerConnectedEvent(peer);
}
void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo)
{
if (PeerDisconnectedEvent != null)
PeerDisconnectedEvent(peer, disconnectInfo);
}
void INetEventListener.OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode)
{
if (NetworkErrorEvent != null)
NetworkErrorEvent(endPoint, socketErrorCode);
}
void INetEventListener.OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod)
{
if (NetworkReceiveEvent != null)
NetworkReceiveEvent(peer, reader, deliveryMethod);
}
void INetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType)
{
if (NetworkReceiveUnconnectedEvent != null)
NetworkReceiveUnconnectedEvent(remoteEndPoint, reader, messageType);
}
void INetEventListener.OnNetworkLatencyUpdate(NetPeer peer, int latency)
{
if (NetworkLatencyUpdateEvent != null)
NetworkLatencyUpdateEvent(peer, latency);
}
void INetEventListener.OnConnectionRequest(ConnectionRequest request)
{
if (ConnectionRequestEvent != null)
ConnectionRequestEvent(request);
}
void IDeliveryEventListener.OnMessageDelivered(NetPeer peer, object userData)
{
if (DeliveryEvent != null)
DeliveryEvent(peer, userData);
}
void INtpEventListener.OnNtpResponse(NtpPacket packet)
{
if (NtpResponseEvent != null)
NtpResponseEvent(packet);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d391f9565d58e44a798d680ec5c11906
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 38985fb72fd8c40eb9de4ce7bfaf401b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
using FlyingWormConsole3.LiteNetLib.Utils;
using System;
using System.Net;
namespace FlyingWormConsole3.LiteNetLib.Layers
{
public sealed class Crc32cLayer : PacketLayerBase
{
public Crc32cLayer() : base(CRC32C.ChecksumSize)
{
}
public override void ProcessInboundPacket(IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length)
{
if (length < NetConstants.HeaderSize + CRC32C.ChecksumSize)
{
NetDebug.WriteError("[NM] DataReceived size: bad!");
//Set length to 0 to have netManager drop the packet.
length = 0;
return;
}
int checksumPoint = length - CRC32C.ChecksumSize;
if (CRC32C.Compute(data, offset, checksumPoint) != BitConverter.ToUInt32(data, checksumPoint))
{
NetDebug.Write("[NM] DataReceived checksum: bad!");
//Set length to 0 to have netManager drop the packet.
length = 0;
return;
}
length -= CRC32C.ChecksumSize;
}
public override void ProcessOutBoundPacket(IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length)
{
FastBitConverter.GetBytes(data, length, CRC32C.Compute(data, offset, length));
length += CRC32C.ChecksumSize;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 03f6f2696c6e848c69a6af33539c5adc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using System.Net;
namespace FlyingWormConsole3.LiteNetLib.Layers
{
public abstract class PacketLayerBase
{
public readonly int ExtraPacketSizeForLayer;
protected PacketLayerBase(int extraPacketSizeForLayer)
{
ExtraPacketSizeForLayer = extraPacketSizeForLayer;
}
public abstract void ProcessInboundPacket(IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length);
public abstract void ProcessOutBoundPacket(IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 20d4d1cdad986436a8f2f4fcc8e3e47d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,60 @@
using System;
using System.Net;
using System.Text;
namespace FlyingWormConsole3.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 == null || _byteKey.Length != key.Length)
_byteKey = new byte[key.Length];
Buffer.BlockCopy(key, 0, _byteKey, 0, key.Length);
}
public override void ProcessInboundPacket(IPEndPoint endPoint, 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]);
}
}
public override void ProcessOutBoundPacket(IPEndPoint endPoint, 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]);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ee39ab3e39a742f59665fde4e2c4f27
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,245 @@
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using FlyingWormConsole3.LiteNetLib.Utils;
namespace FlyingWormConsole3.LiteNetLib
{
public enum NatAddressType
{
Internal,
External
}
public interface INatPunchListener
{
void OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token);
void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token);
}
public class EventBasedNatPunchListener : INatPunchListener
{
public delegate void OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token);
public delegate void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token);
public event OnNatIntroductionRequest NatIntroductionRequest;
public event OnNatIntroductionSuccess NatIntroductionSuccess;
void INatPunchListener.OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token)
{
if(NatIntroductionRequest != null)
NatIntroductionRequest(localEndPoint, remoteEndPoint, token);
}
void INatPunchListener.OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token)
{
if (NatIntroductionSuccess != null)
NatIntroductionSuccess(targetEndPoint, type, token);
}
}
/// <summary>
/// Module for UDP NAT Hole punching operations. Can be accessed from NetManager
/// </summary>
public sealed class NatPunchModule
{
struct RequestEventData
{
public IPEndPoint LocalEndPoint;
public IPEndPoint RemoteEndPoint;
public string Token;
}
struct SuccessEventData
{
public IPEndPoint TargetEndPoint;
public NatAddressType Type;
public string Token;
}
class NatIntroduceRequestPacket
{
public IPEndPoint Internal { get; set; }
public string Token { get; set; }
}
class NatIntroduceResponsePacket
{
public IPEndPoint Internal { get; set; }
public IPEndPoint External { get; set; }
public string Token { get; set; }
}
class NatPunchPacket
{
public string Token { get; set; }
public bool IsExternal { get; set; }
}
private readonly NetSocket _socket;
private readonly Queue<RequestEventData> _requestEvents = new Queue<RequestEventData>();
private readonly Queue<SuccessEventData> _successEvents = new Queue<SuccessEventData>();
private readonly NetDataReader _cacheReader = new NetDataReader();
private readonly NetDataWriter _cacheWriter = new NetDataWriter();
private readonly NetPacketProcessor _netPacketProcessor = new NetPacketProcessor(MaxTokenLength);
private INatPunchListener _natPunchListener;
public const int MaxTokenLength = 256;
internal NatPunchModule(NetSocket socket)
{
_socket = socket;
_netPacketProcessor.SubscribeReusable<NatIntroduceResponsePacket>(OnNatIntroductionResponse);
_netPacketProcessor.SubscribeReusable<NatIntroduceRequestPacket, IPEndPoint>(OnNatIntroductionRequest);
_netPacketProcessor.SubscribeReusable<NatPunchPacket, IPEndPoint>(OnNatPunch);
}
internal void ProcessMessage(IPEndPoint senderEndPoint, NetPacket packet)
{
lock (_cacheReader)
{
_cacheReader.SetSource(packet.RawData, NetConstants.HeaderSize, packet.Size);
_netPacketProcessor.ReadAllPackets(_cacheReader, senderEndPoint);
}
}
public void Init(INatPunchListener listener)
{
_natPunchListener = listener;
}
private void Send<T>(T packet, IPEndPoint target) where T : class, new()
{
SocketError errorCode = 0;
_cacheWriter.Reset();
_cacheWriter.Put((byte)PacketProperty.NatMessage);
_netPacketProcessor.Write(_cacheWriter, packet);
_socket.SendTo(_cacheWriter.Data, 0, _cacheWriter.Length, target, ref errorCode);
}
public void NatIntroduce(
IPEndPoint hostInternal,
IPEndPoint hostExternal,
IPEndPoint clientInternal,
IPEndPoint clientExternal,
string additionalInfo)
{
var req = new NatIntroduceResponsePacket
{
Token = additionalInfo
};
//First packet (server) send to client
req.Internal = hostInternal;
req.External = hostExternal;
Send(req, clientExternal);
//Second packet (client) send to server
req.Internal = clientInternal;
req.External = clientExternal;
Send(req, hostExternal);
}
public void PollEvents()
{
if (_natPunchListener == null || (_successEvents.Count == 0 && _requestEvents.Count == 0))
return;
lock (_successEvents)
{
while (_successEvents.Count > 0)
{
var evt = _successEvents.Dequeue();
_natPunchListener.OnNatIntroductionSuccess(
evt.TargetEndPoint,
evt.Type,
evt.Token);
}
}
lock (_requestEvents)
{
while (_requestEvents.Count > 0)
{
var evt = _requestEvents.Dequeue();
_natPunchListener.OnNatIntroductionRequest(evt.LocalEndPoint, evt.RemoteEndPoint, evt.Token);
}
}
}
public void SendNatIntroduceRequest(string host, int port, string additionalInfo)
{
SendNatIntroduceRequest(NetUtils.MakeEndPoint(host, port), additionalInfo);
}
public void SendNatIntroduceRequest(IPEndPoint masterServerEndPoint, string additionalInfo)
{
//prepare outgoing data
string networkIp = NetUtils.GetLocalIp(LocalAddrType.IPv4);
if (string.IsNullOrEmpty(networkIp))
{
networkIp = NetUtils.GetLocalIp(LocalAddrType.IPv6);
}
Send(
new NatIntroduceRequestPacket
{
Internal = NetUtils.MakeEndPoint(networkIp, _socket.LocalPort),
Token = additionalInfo
},
masterServerEndPoint);
}
//We got request and must introduce
private void OnNatIntroductionRequest(NatIntroduceRequestPacket req, IPEndPoint senderEndPoint)
{
lock (_requestEvents)
{
_requestEvents.Enqueue(new RequestEventData
{
LocalEndPoint = req.Internal,
RemoteEndPoint = senderEndPoint,
Token = req.Token
});
}
}
//We got introduce and must punch
private void OnNatIntroductionResponse(NatIntroduceResponsePacket req)
{
NetDebug.Write(NetLogLevel.Trace, "[NAT] introduction received");
// send internal punch
var punchPacket = new NatPunchPacket {Token = req.Token};
Send(punchPacket, req.Internal);
NetDebug.Write(NetLogLevel.Trace, "[NAT] internal punch sent to " + req.Internal);
// hack for some routers
SocketError errorCode = 0;
_socket.Ttl = 2;
_socket.SendTo(new[] { (byte)PacketProperty.Empty }, 0, 1, req.External, ref errorCode);
// send external punch
_socket.Ttl = NetConstants.SocketTTL;
punchPacket.IsExternal = true;
Send(punchPacket, req.External);
NetDebug.Write(NetLogLevel.Trace, "[NAT] external punch sent to " + req.External);
}
//We got punch and can connect
private void OnNatPunch(NatPunchPacket req, IPEndPoint senderEndPoint)
{
//Read info
NetDebug.Write(NetLogLevel.Trace, "[NAT] punch received from {0} - additional info: {1}",
senderEndPoint, req.Token);
//Release punch success to client; enabling him to Connect() to Sender if token is ok
lock (_successEvents)
{
_successEvents.Enqueue(new SuccessEventData
{
TargetEndPoint = senderEndPoint,
Type = req.IsExternal ? NatAddressType.External : NatAddressType.Internal,
Token = req.Token
});
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 11f3508667cc14e3797a49d4695ffdd8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,74 @@
namespace FlyingWormConsole3.LiteNetLib
{
/// <summary>
/// Sending method type
/// </summary>
public enum DeliveryMethod : byte
{
/// <summary>
/// Unreliable. Packets can be dropped, can be duplicated, can arrive without order.
/// </summary>
Unreliable = 4,
/// <summary>
/// Reliable. Packets won't be dropped, won't be duplicated, can arrive without order.
/// </summary>
ReliableUnordered = 0,
/// <summary>
/// Unreliable. Packets can be dropped, won't be duplicated, will arrive in order.
/// </summary>
Sequenced = 1,
/// <summary>
/// Reliable and ordered. Packets won't be dropped, won't be duplicated, will arrive in order.
/// </summary>
ReliableOrdered = 2,
/// <summary>
/// Reliable only last packet. Packets can be dropped (except the last one), won't be duplicated, will arrive in order.
/// Cannot be fragmented
/// </summary>
ReliableSequenced = 3
}
/// <summary>
/// Network constants. Can be tuned from sources for your purposes.
/// </summary>
public static class NetConstants
{
//can be tuned
public const int DefaultWindowSize = 64;
public const int SocketBufferSize = 1024 * 1024; //1mb
public const int SocketTTL = 255;
public const int HeaderSize = 1;
public const int ChanneledHeaderSize = 4;
public const int FragmentHeaderSize = 6;
public const int FragmentedHeaderTotalSize = ChanneledHeaderSize + FragmentHeaderSize;
public const ushort MaxSequence = 32768;
public const ushort HalfMaxSequence = MaxSequence / 2;
//protocol
internal const int ProtocolId = 11;
internal const int MaxUdpHeaderSize = 68;
internal static readonly int[] PossibleMtu =
{
576 - MaxUdpHeaderSize, //minimal (RFC 1191)
1024, //most games standard
1232 - MaxUdpHeaderSize,
1460 - MaxUdpHeaderSize, //google cloud
1472 - MaxUdpHeaderSize, //VPN
1492 - MaxUdpHeaderSize, //Ethernet with LLC and SNAP, PPPoE (RFC 1042)
1500 - MaxUdpHeaderSize //Ethernet II (RFC 1191)
};
internal static readonly int MaxPacketSize = PossibleMtu[PossibleMtu.Length - 1];
//peer specific
public const byte MaxConnectionNumber = 4;
public const int PacketPoolSize = 1000;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 02abb4740bff94f28bdd538839339932
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,92 @@
using System;
using System.Diagnostics;
namespace FlyingWormConsole3.LiteNetLib
{
public class InvalidPacketException : ArgumentException
{
public InvalidPacketException(string message) : base(message)
{
}
}
public class TooBigPacketException : InvalidPacketException
{
public TooBigPacketException(string message) : base(message)
{
}
}
public enum NetLogLevel
{
Warning,
Error,
Trace,
Info
}
/// <summary>
/// Interface to implement for your own logger
/// </summary>
public interface INetLogger
{
void WriteNet(NetLogLevel level, string str, params object[] args);
}
/// <summary>
/// Static class for defining your own LiteNetLib logger instead of Console.WriteLine
/// or Debug.Log if compiled with UNITY flag
/// </summary>
public static class NetDebug
{
public static INetLogger Logger = null;
private static readonly object DebugLogLock = new object();
private static void WriteLogic(NetLogLevel logLevel, string str, params object[] args)
{
lock (DebugLogLock)
{
if (Logger == null)
{
#if UNITY_4 || UNITY_5 || UNITY_5_3_OR_NEWER
UnityEngine.Debug.Log(string.Format(str, args));
#else
Console.WriteLine(str, args);
#endif
}
else
{
Logger.WriteNet(logLevel, str, args);
}
}
}
[Conditional("DEBUG_MESSAGES")]
internal static void Write(string str, params object[] args)
{
WriteLogic(NetLogLevel.Trace, str, args);
}
[Conditional("DEBUG_MESSAGES")]
internal static void Write(NetLogLevel level, string str, params object[] args)
{
WriteLogic(level, str, args);
}
[Conditional("DEBUG_MESSAGES"), Conditional("DEBUG")]
internal static void WriteForce(string str, params object[] args)
{
WriteLogic(NetLogLevel.Trace, str, args);
}
[Conditional("DEBUG_MESSAGES"), Conditional("DEBUG")]
internal static void WriteForce(NetLogLevel level, string str, params object[] args)
{
WriteLogic(level, str, args);
}
internal static void WriteError(string str, params object[] args)
{
WriteLogic(NetLogLevel.Error, str, args);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 78dc00ceb66ac4fdfa8c3957763522ba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a0197124da84847d8855d5f690b8c653
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,270 @@
using System;
using System.Net;
using FlyingWormConsole3.LiteNetLib.Utils;
namespace FlyingWormConsole3.LiteNetLib
{
internal enum PacketProperty : byte
{
Unreliable,
Channeled,
Ack,
Ping,
Pong,
ConnectRequest,
ConnectAccept,
Disconnect,
UnconnectedMessage,
MtuCheck,
MtuOk,
Broadcast,
Merged,
ShutdownOk,
PeerNotFound,
InvalidProtocol,
NatMessage,
Empty
}
internal sealed class NetPacket
{
private static readonly int LastProperty = Enum.GetValues(typeof(PacketProperty)).Length;
private static readonly int[] HeaderSizes;
static NetPacket()
{
HeaderSizes = new int[LastProperty+1];
for (int i = 0; i < HeaderSizes.Length; i++)
{
switch ((PacketProperty)i)
{
case PacketProperty.Channeled:
case PacketProperty.Ack:
HeaderSizes[i] = NetConstants.ChanneledHeaderSize;
break;
case PacketProperty.Ping:
HeaderSizes[i] = NetConstants.HeaderSize + 2;
break;
case PacketProperty.ConnectRequest:
HeaderSizes[i] = NetConnectRequestPacket.HeaderSize;
break;
case PacketProperty.ConnectAccept:
HeaderSizes[i] = NetConnectAcceptPacket.Size;
break;
case PacketProperty.Disconnect:
HeaderSizes[i] = NetConstants.HeaderSize + 8;
break;
case PacketProperty.Pong:
HeaderSizes[i] = NetConstants.HeaderSize + 10;
break;
default:
HeaderSizes[i] = NetConstants.HeaderSize;
break;
}
}
}
//Header
public PacketProperty Property
{
get { return (PacketProperty)(RawData[0] & 0x1F); }
set { RawData[0] = (byte)((RawData[0] & 0xE0) | (byte)value); }
}
public byte ConnectionNumber
{
get { return (byte)((RawData[0] & 0x60) >> 5); }
set { RawData[0] = (byte) ((RawData[0] & 0x9F) | (value << 5)); }
}
public ushort Sequence
{
get { return BitConverter.ToUInt16(RawData, 1); }
set { FastBitConverter.GetBytes(RawData, 1, value); }
}
public bool IsFragmented
{
get { return (RawData[0] & 0x80) != 0; }
}
public void MarkFragmented()
{
RawData[0] |= 0x80; //set first bit
}
public byte ChannelId
{
get { return RawData[3]; }
set { RawData[3] = value; }
}
public ushort FragmentId
{
get { return BitConverter.ToUInt16(RawData, 4); }
set { FastBitConverter.GetBytes(RawData, 4, value); }
}
public ushort FragmentPart
{
get { return BitConverter.ToUInt16(RawData, 6); }
set { FastBitConverter.GetBytes(RawData, 6, value); }
}
public ushort FragmentsTotal
{
get { return BitConverter.ToUInt16(RawData, 8); }
set { FastBitConverter.GetBytes(RawData, 8, value); }
}
//Data
public byte[] RawData;
public int Size;
//Delivery
public object UserData;
//Pool node
public NetPacket Next;
#if DEBUG_REFCOUNT
public int RefCount = 1;
#endif
public NetPacket(int size)
{
RawData = new byte[size];
Size = size;
}
public NetPacket(PacketProperty property, int size)
{
size += GetHeaderSize(property);
RawData = new byte[size];
Property = property;
Size = size;
}
public static int GetHeaderSize(PacketProperty property)
{
return HeaderSizes[(int)property];
}
public int GetHeaderSize()
{
return HeaderSizes[RawData[0] & 0x1F];
}
public bool Verify()
{
byte property = (byte)(RawData[0] & 0x1F);
if (property > LastProperty)
return false;
int headerSize = HeaderSizes[property];
bool fragmented = (RawData[0] & 0x80) != 0;
return Size >= headerSize && (!fragmented || Size >= headerSize + NetConstants.FragmentHeaderSize);
}
}
internal sealed class NetConnectRequestPacket
{
public const int HeaderSize = 14;
public readonly long ConnectionTime;
public readonly byte ConnectionNumber;
public readonly byte[] TargetAddress;
public readonly NetDataReader Data;
private NetConnectRequestPacket(long connectionTime, byte connectionNumber, byte[] targetAddress, NetDataReader data)
{
ConnectionTime = connectionTime;
ConnectionNumber = connectionNumber;
TargetAddress = targetAddress;
Data = data;
}
public static int GetProtocolId(NetPacket packet)
{
return BitConverter.ToInt32(packet.RawData, 1);
}
public static NetConnectRequestPacket FromData(NetPacket packet)
{
if (packet.ConnectionNumber >= NetConstants.MaxConnectionNumber)
return null;
//Getting new id for peer
long connectionId = BitConverter.ToInt64(packet.RawData, 5);
//Get target address
int addrSize = packet.RawData[13];
if (addrSize != 16 && addrSize != 28)
return null;
byte[] addressBytes = new byte[addrSize];
Buffer.BlockCopy(packet.RawData, 14, addressBytes, 0, addrSize);
// Read data and create request
var reader = new NetDataReader(null, 0, 0);
if (packet.Size > HeaderSize+addrSize)
reader.SetSource(packet.RawData, HeaderSize + addrSize, packet.Size);
return new NetConnectRequestPacket(connectionId, packet.ConnectionNumber, addressBytes, reader);
}
public static NetPacket Make(NetDataWriter connectData, SocketAddress addressBytes, long connectId)
{
//Make initial packet
var packet = new NetPacket(PacketProperty.ConnectRequest, connectData.Length+addressBytes.Size);
//Add data
FastBitConverter.GetBytes(packet.RawData, 1, NetConstants.ProtocolId);
FastBitConverter.GetBytes(packet.RawData, 5, connectId);
packet.RawData[13] = (byte)addressBytes.Size;
for (int i = 0; i < addressBytes.Size; i++)
packet.RawData[14+i] = addressBytes[i];
Buffer.BlockCopy(connectData.Data, 0, packet.RawData, 14+addressBytes.Size, connectData.Length);
return packet;
}
}
internal sealed class NetConnectAcceptPacket
{
public const int Size = 11;
public readonly long ConnectionId;
public readonly byte ConnectionNumber;
public readonly bool IsReusedPeer;
private NetConnectAcceptPacket(long connectionId, byte connectionNumber, bool isReusedPeer)
{
ConnectionId = connectionId;
ConnectionNumber = connectionNumber;
IsReusedPeer = isReusedPeer;
}
public static NetConnectAcceptPacket FromData(NetPacket packet)
{
if (packet.Size > Size)
return null;
long connectionId = BitConverter.ToInt64(packet.RawData, 1);
//check connect num
byte connectionNumber = packet.RawData[9];
if (connectionNumber >= NetConstants.MaxConnectionNumber)
return null;
//check reused flag
byte isReused = packet.RawData[10];
if (isReused > 1)
return null;
return new NetConnectAcceptPacket(connectionId, connectionNumber, isReused == 1);
}
public static NetPacket Make(long connectId, byte connectNum, bool reusedPeer)
{
var packet = new NetPacket(PacketProperty.ConnectAccept, 0);
FastBitConverter.GetBytes(packet.RawData, 1, connectId);
packet.RawData[9] = connectNum;
packet.RawData[10] = (byte)(reusedPeer ? 1 : 0);
return packet;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7aa9ed55f53fa48569ccd0963c50d8da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,76 @@
using System;
using System.Threading;
namespace FlyingWormConsole3.LiteNetLib
{
internal sealed class NetPacketPool
{
private NetPacket _head;
private int _count;
private readonly object _lock = new object();
public NetPacket GetWithData(PacketProperty property, byte[] data, int start, int 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 GetWithProperty(PacketProperty property)
{
NetPacket packet = GetPacket(NetPacket.GetHeaderSize(property));
packet.Property = property;
return packet;
}
public NetPacket GetPacket(int size)
{
if (size > NetConstants.MaxPacketSize)
return new NetPacket(size);
NetPacket packet;
lock (_lock)
{
packet = _head;
if (packet == null)
return new NetPacket(size);
_head = _head.Next;
}
Interlocked.Decrement(ref _count);
packet.Size = size;
if (packet.RawData.Length < size)
packet.RawData = new byte[size];
return packet;
}
public void Recycle(NetPacket packet)
{
if (packet.RawData.Length > NetConstants.MaxPacketSize || _count >= NetConstants.PacketPoolSize)
{
//Don't pool big packets. Save memory
return;
}
Interlocked.Increment(ref _count);
//Clean fragmented flag
packet.RawData[0] = 0;
lock (_lock)
{
packet.Next = _head;
_head = packet;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3637381933a4745b996d4dd48cd71efe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 39ca2e83856ea4ba0a0100a00089e695
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,543 @@
#if UNITY_5_3_OR_NEWER
#define UNITY
#if UNITY_IOS && !UNITY_EDITOR
using UnityEngine;
#endif
#endif
#if NETSTANDARD || NETCOREAPP
using System.Runtime.InteropServices;
#endif
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace FlyingWormConsole3.LiteNetLib
{
#if UNITY_IOS && !UNITY_EDITOR
public class UnitySocketFix : MonoBehaviour
{
internal IPAddress BindAddrIPv4;
internal IPAddress BindAddrIPv6;
internal bool Reuse;
internal IPv6Mode IPv6;
internal int Port;
internal bool Paused;
internal NetSocket Socket;
internal bool ManualMode;
private void Update()
{
if (Socket == null)
Destroy(gameObject);
}
private void OnApplicationPause(bool pause)
{
if (Socket == null)
return;
if (pause)
{
Paused = true;
Socket.Close(true);
}
else if (Paused)
{
if (!Socket.Bind(BindAddrIPv4, BindAddrIPv6, Port, Reuse, IPv6, ManualMode))
{
NetDebug.WriteError("[S] Cannot restore connection \"{0}\",\"{1}\" port {2}", BindAddrIPv4, BindAddrIPv6, Port);
Socket.OnErrorRestore();
}
}
}
}
#endif
internal sealed class NetSocket
{
public const int ReceivePollingTime = 500000; //0.5 second
private Socket _udpSocketv4;
private Socket _udpSocketv6;
private Thread _threadv4;
private Thread _threadv6;
private IPEndPoint _bufferEndPointv4;
private IPEndPoint _bufferEndPointv6;
private readonly NetManager _listener;
private const int SioUdpConnreset = -1744830452; //SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12
private static readonly IPAddress MulticastAddressV6 = IPAddress.Parse("ff02::1");
internal static readonly bool IPv6Support;
#if UNITY_IOS && !UNITY_EDITOR
private UnitySocketFix _unitySocketFix;
public void OnErrorRestore()
{
Close(false);
_listener.OnMessageReceived(null, SocketError.NotConnected, new IPEndPoint(0,0));
}
#endif
public int LocalPort { get; private set; }
public volatile bool IsRunning;
public short Ttl
{
get
{
#if UNITY_SWITCH
return 0;
#else
if (_udpSocketv4.AddressFamily == AddressFamily.InterNetworkV6)
return (short)_udpSocketv4.GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.HopLimit);
return _udpSocketv4.Ttl;
#endif
}
set
{
#if !UNITY_SWITCH
if (_udpSocketv4.AddressFamily == AddressFamily.InterNetworkV6)
_udpSocketv4.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
else
_udpSocketv4.Ttl = value;
#endif
}
}
static NetSocket()
{
#if DISABLE_IPV6 || (!UNITY_EDITOR && ENABLE_IL2CPP && !UNITY_2018_3_OR_NEWER)
IPv6Support = false;
#elif !UNITY_2019_1_OR_NEWER && !UNITY_2018_4_OR_NEWER && (!UNITY_EDITOR && ENABLE_IL2CPP && UNITY_2018_3_OR_NEWER)
string version = UnityEngine.Application.unityVersion;
IPv6Support = Socket.OSSupportsIPv6 && int.Parse(version.Remove(version.IndexOf('f')).Split('.')[2]) >= 6;
#elif UNITY_2018_2_OR_NEWER
IPv6Support = Socket.OSSupportsIPv6;
#elif UNITY
#pragma warning disable 618
IPv6Support = Socket.SupportsIPv6;
#pragma warning restore 618
#else
IPv6Support = Socket.OSSupportsIPv6;
#endif
}
public NetSocket(NetManager 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 bool ProcessError(SocketException ex, EndPoint bufferEndPoint)
{
switch (ex.SocketErrorCode)
{
#if UNITY_IOS && !UNITY_EDITOR
case SocketError.NotConnected:
#endif
case SocketError.Interrupted:
case SocketError.NotSocket:
return true;
case SocketError.ConnectionReset:
case SocketError.MessageSize:
case SocketError.TimedOut:
NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}",
(int)ex.SocketErrorCode, ex.ToString());
break;
default:
NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode,
ex.ToString());
_listener.OnMessageReceived(null, ex.SocketErrorCode, (IPEndPoint)bufferEndPoint);
break;
}
return false;
}
public void ManualReceive()
{
ManualReceive(_udpSocketv4, _bufferEndPointv4);
if (_udpSocketv6 != null && _udpSocketv6 != _udpSocketv4)
ManualReceive(_udpSocketv6, _bufferEndPointv6);
}
private bool ManualReceive(Socket socket, EndPoint bufferEndPoint)
{
//Reading data
try
{
int available = socket.Available;
if (available == 0)
return false;
while (available > 0)
{
var packet = _listener.NetPacketPool.GetPacket(NetConstants.MaxPacketSize);
packet.Size = socket.ReceiveFrom(packet.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None,
ref bufferEndPoint);
NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(), packet.Size);
_listener.OnMessageReceived(packet, 0, (IPEndPoint)bufferEndPoint);
available -= packet.Size;
}
}
catch (SocketException ex)
{
return ProcessError(ex, bufferEndPoint);
}
catch (ObjectDisposedException)
{
return true;
}
return false;
}
private void ReceiveLogic(object state)
{
Socket socket = (Socket)state;
EndPoint bufferEndPoint = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);
while (IsActive())
{
NetPacket packet;
//Reading data
try
{
if (socket.Available == 0 && !socket.Poll(ReceivePollingTime, SelectMode.SelectRead))
continue;
packet = _listener.NetPacketPool.GetPacket(NetConstants.MaxPacketSize);
packet.Size = socket.ReceiveFrom(packet.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None,
ref bufferEndPoint);
}
catch (SocketException ex)
{
if (ProcessError(ex, bufferEndPoint))
return;
continue;
}
catch (ObjectDisposedException)
{
return;
}
//All ok!
NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(), packet.Size);
_listener.OnMessageReceived(packet, 0, (IPEndPoint)bufferEndPoint);
}
}
public bool Bind(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool reuseAddress, IPv6Mode ipv6Mode, bool manualMode)
{
if (IsActive())
return false;
bool dualMode = ipv6Mode == IPv6Mode.DualMode && IPv6Support;
_udpSocketv4 = new Socket(
dualMode ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
if (!BindSocket(_udpSocketv4, new IPEndPoint(dualMode ? addressIPv6 : addressIPv4, port), reuseAddress, ipv6Mode))
return false;
LocalPort = ((IPEndPoint) _udpSocketv4.LocalEndPoint).Port;
#if UNITY_IOS && !UNITY_EDITOR
if (_unitySocketFix == null)
{
var unityFixObj = new GameObject("LiteNetLib_UnitySocketFix");
GameObject.DontDestroyOnLoad(unityFixObj);
_unitySocketFix = unityFixObj.AddComponent<UnitySocketFix>();
_unitySocketFix.Socket = this;
_unitySocketFix.BindAddrIPv4 = addressIPv4;
_unitySocketFix.BindAddrIPv6 = addressIPv6;
_unitySocketFix.Reuse = reuseAddress;
_unitySocketFix.Port = LocalPort;
_unitySocketFix.IPv6 = ipv6Mode;
_unitySocketFix.ManualMode = manualMode;
}
else
{
_unitySocketFix.Paused = false;
}
#endif
if (dualMode)
_udpSocketv6 = _udpSocketv4;
IsRunning = true;
if (!manualMode)
{
_threadv4 = new Thread(ReceiveLogic)
{
Name = "SocketThreadv4(" + LocalPort + ")",
IsBackground = true
};
_threadv4.Start(_udpSocketv4);
}
else
{
_bufferEndPointv4 = new IPEndPoint(IPAddress.Any, 0);
}
//Check IPv6 support
if (!IPv6Support || ipv6Mode != IPv6Mode.SeparateSocket)
return true;
_udpSocketv6 = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
//Use one port for two sockets
if (BindSocket(_udpSocketv6, new IPEndPoint(addressIPv6, LocalPort), reuseAddress, ipv6Mode))
{
if (manualMode)
{
_bufferEndPointv6 = new IPEndPoint(IPAddress.IPv6Any, 0);
}
else
{
_threadv6 = new Thread(ReceiveLogic)
{
Name = "SocketThreadv6(" + LocalPort + ")",
IsBackground = true
};
_threadv6.Start(_udpSocketv6);
}
}
return true;
}
private bool BindSocket(Socket socket, IPEndPoint ep, bool reuseAddress, IPv6Mode ipv6Mode)
{
//Setup socket
socket.ReceiveTimeout = 500;
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);
}
catch
{
//ignored
}
#endif
try
{
socket.ExclusiveAddressUse = !reuseAddress;
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuseAddress);
}
catch
{
//Unity with IL2CPP throws an exception here, it doesn't matter in most cases so just ignore it
}
if (socket.AddressFamily == AddressFamily.InterNetwork)
{
Ttl = NetConstants.SocketTTL;
#if NETSTANDARD || NETCOREAPP
if(!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
#endif
try { socket.DontFragment = true; }
catch (SocketException e)
{
NetDebug.WriteError("[B]DontFragment error: {0}", e.SocketErrorCode);
}
try { socket.EnableBroadcast = true; }
catch (SocketException e)
{
NetDebug.WriteError("[B]Broadcast error: {0}", e.SocketErrorCode);
}
}
else //IPv6 specific
{
if (ipv6Mode == IPv6Mode.DualMode)
{
try
{
//Disable IPv6 only mode
socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
}
catch(Exception e)
{
NetDebug.WriteError("[B]Bind exception (dualmode setting): {0}", e.ToString());
}
}
}
//Bind
try
{
socket.Bind(ep);
NetDebug.Write(NetLogLevel.Trace, "[B]Successfully binded to port: {0}", ((IPEndPoint)socket.LocalEndPoint).Port);
//join multicast
if (socket.AddressFamily == AddressFamily.InterNetworkV6)
{
try
{
#if !UNITY
socket.SetSocketOption(
SocketOptionLevel.IPv6,
SocketOptionName.AddMembership,
new IPv6MulticastOption(MulticastAddressV6));
#endif
}
catch (Exception)
{
// Unity3d throws exception - ignored
}
}
}
catch (SocketException bindException)
{
switch (bindException.SocketErrorCode)
{
//IPv6 bind fix
case SocketError.AddressAlreadyInUse:
if (socket.AddressFamily == AddressFamily.InterNetworkV6 && ipv6Mode != IPv6Mode.DualMode)
{
try
{
//Set IPv6Only
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;
}
break;
//hack for iOS (Unity3D)
case SocketError.AddressFamilyNotSupported:
return true;
}
NetDebug.WriteError("[B]Bind exception: {0}, errorCode: {1}", bindException.ToString(), bindException.SocketErrorCode);
return false;
}
return true;
}
public bool SendBroadcast(byte[] data, int offset, int size, int port)
{
if (!IsActive())
return false;
bool broadcastSuccess = false;
bool multicastSuccess = false;
try
{
broadcastSuccess = _udpSocketv4.SendTo(
data,
offset,
size,
SocketFlags.None,
new IPEndPoint(IPAddress.Broadcast, port)) > 0;
if (_udpSocketv6 != null)
{
multicastSuccess = _udpSocketv6.SendTo(
data,
offset,
size,
SocketFlags.None,
new IPEndPoint(MulticastAddressV6, port)) > 0;
}
}
catch (Exception ex)
{
NetDebug.WriteError("[S][MCAST]" + ex);
return broadcastSuccess;
}
return broadcastSuccess || multicastSuccess;
}
public int SendTo(byte[] data, int offset, int size, IPEndPoint remoteEndPoint, ref SocketError errorCode)
{
if (!IsActive())
return 0;
try
{
var socket = _udpSocketv4;
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6 && IPv6Support)
socket = _udpSocketv6;
int result = socket.SendTo(data, offset, size, SocketFlags.None, remoteEndPoint);
NetDebug.Write(NetLogLevel.Trace, "[S]Send packet to {0}, result: {1}", remoteEndPoint, result);
return result;
}
catch (SocketException ex)
{
switch (ex.SocketErrorCode)
{
case SocketError.NoBufferSpaceAvailable:
case SocketError.Interrupted:
return 0;
case SocketError.MessageSize: //do nothing
break;
default:
NetDebug.WriteError("[S]" + ex);
break;
}
errorCode = ex.SocketErrorCode;
return -1;
}
catch (Exception ex)
{
NetDebug.WriteError("[S]" + ex);
return -1;
}
}
public void Close(bool suspend)
{
if (!suspend)
{
IsRunning = false;
#if UNITY_IOS && !UNITY_EDITOR
_unitySocketFix.Socket = null;
_unitySocketFix = null;
#endif
}
//cleanup dual mode
if (_udpSocketv4 == _udpSocketv6)
_udpSocketv6 = null;
if (_udpSocketv4 != null)
_udpSocketv4.Close();
if (_udpSocketv6 != null)
_udpSocketv6.Close();
_udpSocketv4 = null;
_udpSocketv6 = null;
if (_threadv4 != null && _threadv4 != Thread.CurrentThread)
_threadv4.Join();
if (_threadv6 != null && _threadv6 != Thread.CurrentThread)
_threadv6.Join();
_threadv4 = null;
_threadv6 = null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c517b909a8c704eae91d4eccf06bc8a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,98 @@
using System.Threading;
namespace FlyingWormConsole3.LiteNetLib
{
public sealed class NetStatistics
{
private long _packetsSent;
private long _packetsReceived;
private long _bytesSent;
private long _bytesReceived;
private long _packetLoss;
public long PacketsSent
{
get { return Interlocked.Read(ref _packetsSent); }
}
public long PacketsReceived
{
get { return Interlocked.Read(ref _packetsReceived); }
}
public long BytesSent
{
get { return Interlocked.Read(ref _bytesSent); }
}
public long BytesReceived
{
get { return Interlocked.Read(ref _bytesReceived); }
}
public long PacketLoss
{
get { return Interlocked.Read(ref _packetLoss); }
}
public long PacketLossPercent
{
get
{
long sent = PacketsSent, loss = PacketLoss;
return sent == 0 ? 0 : loss * 100 / sent;
}
}
public void Reset()
{
Interlocked.Exchange(ref _packetsSent, 0);
Interlocked.Exchange(ref _packetsReceived, 0);
Interlocked.Exchange(ref _bytesSent, 0);
Interlocked.Exchange(ref _bytesReceived, 0);
Interlocked.Exchange(ref _packetLoss, 0);
}
public void IncrementPacketsSent()
{
Interlocked.Increment(ref _packetsSent);
}
public void IncrementPacketsReceived()
{
Interlocked.Increment(ref _packetsReceived);
}
public void AddBytesSent(long bytesSent)
{
Interlocked.Add(ref _bytesSent, bytesSent);
}
public void AddBytesReceived(long bytesReceived)
{
Interlocked.Add(ref _bytesReceived, bytesReceived);
}
public void IncrementPacketLoss()
{
Interlocked.Increment(ref _packetLoss);
}
public void AddPacketLoss(long packetLoss)
{
Interlocked.Add(ref _packetLoss, packetLoss);
}
public override string ToString()
{
return
string.Format(
"BytesReceived: {0}\nPacketsReceived: {1}\nBytesSent: {2}\nPacketsSent: {3}\nPacketLoss: {4}\nPacketLossPercent: {5}\n",
BytesReceived,
PacketsReceived,
BytesSent,
PacketsSent,
PacketLoss,
PacketLossPercent);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95b0631b1ed3f44169d8bf6632f9e567
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,185 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
namespace FlyingWormConsole3.LiteNetLib
{
/// <summary>
/// Address type that you want to receive from NetUtils.GetLocalIp method
/// </summary>
[Flags]
public enum LocalAddrType
{
IPv4 = 1,
IPv6 = 2,
All = IPv4 | IPv6
}
/// <summary>
/// Some specific network utilities
/// </summary>
public static class NetUtils
{
public static IPEndPoint MakeEndPoint(string hostStr, int port)
{
return new IPEndPoint(ResolveAddress(hostStr), port);
}
public static IPAddress ResolveAddress(string hostStr)
{
if(hostStr == "localhost")
return IPAddress.Loopback;
IPAddress ipAddress;
if (!IPAddress.TryParse(hostStr, out ipAddress))
{
if (NetSocket.IPv6Support)
ipAddress = ResolveAddress(hostStr, AddressFamily.InterNetworkV6);
if (ipAddress == null)
ipAddress = ResolveAddress(hostStr, AddressFamily.InterNetwork);
}
if (ipAddress == null)
throw new ArgumentException("Invalid address: " + hostStr);
return ipAddress;
}
public static IPAddress ResolveAddress(string hostStr, AddressFamily addressFamily)
{
IPAddress[] addresses = Dns.GetHostEntry(hostStr).AddressList;
foreach (IPAddress ip in addresses)
{
if (ip.AddressFamily == addressFamily)
{
return ip;
}
}
return null;
}
/// <summary>
/// Get all local ip addresses
/// </summary>
/// <param name="addrType">type of address (IPv4, IPv6 or both)</param>
/// <returns>List with all local ip addresses</returns>
public static List<string> GetLocalIpList(LocalAddrType addrType)
{
List<string> targetList = new List<string>();
GetLocalIpList(targetList, addrType);
return targetList;
}
/// <summary>
/// Get all local ip addresses (non alloc version)
/// </summary>
/// <param name="targetList">result list</param>
/// <param name="addrType">type of address (IPv4, IPv6 or both)</param>
public static void GetLocalIpList(IList<string> targetList, LocalAddrType addrType)
{
bool ipv4 = (addrType & LocalAddrType.IPv4) == LocalAddrType.IPv4;
bool ipv6 = (addrType & LocalAddrType.IPv6) == LocalAddrType.IPv6;
try
{
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
//Skip loopback and disabled network interfaces
if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback ||
ni.OperationalStatus != OperationalStatus.Up)
continue;
var ipProps = ni.GetIPProperties();
//Skip address without gateway
if (ipProps.GatewayAddresses.Count == 0)
continue;
foreach (UnicastIPAddressInformation ip in ipProps.UnicastAddresses)
{
var address = ip.Address;
if ((ipv4 && address.AddressFamily == AddressFamily.InterNetwork) ||
(ipv6 && address.AddressFamily == AddressFamily.InterNetworkV6))
targetList.Add(address.ToString());
}
}
}
catch
{
//ignored
}
//Fallback mode (unity android)
if (targetList.Count == 0)
{
IPAddress[] addresses = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
foreach (IPAddress ip in addresses)
{
if((ipv4 && ip.AddressFamily == AddressFamily.InterNetwork) ||
(ipv6 && ip.AddressFamily == AddressFamily.InterNetworkV6))
targetList.Add(ip.ToString());
}
}
if (targetList.Count == 0)
{
if(ipv4)
targetList.Add("127.0.0.1");
if(ipv6)
targetList.Add("::1");
}
}
private static readonly List<string> IpList = new List<string>();
/// <summary>
/// Get first detected local ip address
/// </summary>
/// <param name="addrType">type of address (IPv4, IPv6 or both)</param>
/// <returns>IP address if available. Else - string.Empty</returns>
public static string GetLocalIp(LocalAddrType addrType)
{
lock (IpList)
{
IpList.Clear();
GetLocalIpList(IpList, addrType);
return IpList.Count == 0 ? string.Empty : IpList[0];
}
}
// ===========================================
// Internal and debug log related stuff
// ===========================================
internal static void PrintInterfaceInfos()
{
NetDebug.WriteForce(NetLogLevel.Info, "IPv6Support: {0}", NetSocket.IPv6Support);
try
{
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork ||
ip.Address.AddressFamily == AddressFamily.InterNetworkV6)
{
NetDebug.WriteForce(
NetLogLevel.Info,
"Interface: {0}, Type: {1}, Ip: {2}, OpStatus: {3}",
ni.Name,
ni.NetworkInterfaceType.ToString(),
ip.Address.ToString(),
ni.OperationalStatus.ToString());
}
}
}
}
catch (Exception e)
{
NetDebug.WriteForce(NetLogLevel.Info, "Error while getting interface infos: {0}", e.ToString());
}
}
internal static int RelativeSequenceNumber(int number, int expected)
{
return (number - expected + NetConstants.MaxSequence + NetConstants.HalfMaxSequence) % NetConstants.MaxSequence - NetConstants.HalfMaxSequence;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0b27974b2b4714973a8f5a3ea4036677
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,341 @@
using System;
namespace FlyingWormConsole3.LiteNetLib
{
internal sealed class ReliableChannel : BaseChannel
{
private struct PendingPacket
{
private NetPacket _packet;
private long _timeStamp;
private bool _isSent;
public override string ToString()
{
return _packet == null ? "Empty" : _packet.Sequence.ToString();
}
public void Init(NetPacket packet)
{
_packet = packet;
_isSent = false;
}
public void TrySend(long currentTime, NetPeer peer, out bool hasPacket)
{
if (_packet == null)
{
hasPacket = false;
return;
}
hasPacket = true;
if (_isSent) //check send time
{
double resendDelay = peer.ResendDelay * TimeSpan.TicksPerMillisecond;
double packetHoldTime = currentTime - _timeStamp;
if (packetHoldTime < resendDelay)
return;
NetDebug.Write("[RC]Resend: {0} > {1}", (int)packetHoldTime, resendDelay);
}
_timeStamp = currentTime;
_isSent = true;
peer.SendUserData(_packet);
}
public bool Clear(NetPeer peer)
{
if (_packet != null)
{
peer.RecycleAndDeliver(_packet);
_packet = null;
return true;
}
return false;
}
}
private readonly NetPacket _outgoingAcks; //for send acks
private readonly PendingPacket[] _pendingPackets; //for unacked packets and duplicates
private readonly NetPacket[] _receivedPackets; //for order
private readonly bool[] _earlyReceived; //for unordered
private int _localSeqence;
private int _remoteSequence;
private int _localWindowStart;
private int _remoteWindowStart;
private bool _mustSendAcks;
private readonly DeliveryMethod _deliveryMethod;
private readonly bool _ordered;
private readonly int _windowSize;
private const int BitsInByte = 8;
private readonly byte _id;
public ReliableChannel(NetPeer peer, bool ordered, byte id) : base(peer)
{
_id = id;
_windowSize = NetConstants.DefaultWindowSize;
_ordered = ordered;
_pendingPackets = new PendingPacket[_windowSize];
for (int i = 0; i < _pendingPackets.Length; i++)
_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;
_remoteSequence = 0;
_remoteWindowStart = 0;
_outgoingAcks = new NetPacket(PacketProperty.Ack, (_windowSize - 1) / BitsInByte + 2) {ChannelId = id};
}
//ProcessAck in packet
private void ProcessAck(NetPacket packet)
{
if (packet.Size != _outgoingAcks.Size)
{
NetDebug.Write("[PA]Invalid acks packet size");
return;
}
ushort ackWindowStart = packet.Sequence;
int windowRel = NetUtils.RelativeSequenceNumber(_localWindowStart, ackWindowStart);
if (ackWindowStart >= NetConstants.MaxSequence || windowRel < 0)
{
NetDebug.Write("[PA]Bad window start");
return;
}
//check relevance
if (windowRel >= _windowSize)
{
NetDebug.Write("[PA]Old acks");
return;
}
byte[] acksData = packet.RawData;
lock (_pendingPackets)
{
for (int pendingSeq = _localWindowStart;
pendingSeq != _localSeqence;
pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
{
int rel = NetUtils.RelativeSequenceNumber(pendingSeq, ackWindowStart);
if (rel >= _windowSize)
{
NetDebug.Write("[PA]REL: " + rel);
break;
}
int pendingIdx = pendingSeq % _windowSize;
int currentByte = NetConstants.ChanneledHeaderSize + pendingIdx / BitsInByte;
int currentBit = pendingIdx % BitsInByte;
if ((acksData[currentByte] & (1 << currentBit)) == 0)
{
if (Peer.NetManager.EnableStatistics)
{
Peer.Statistics.IncrementPacketLoss();
Peer.NetManager.Statistics.IncrementPacketLoss();
}
//Skip false ack
NetDebug.Write("[PA]False ack: {0}", pendingSeq);
continue;
}
if (pendingSeq == _localWindowStart)
{
//Move window
_localWindowStart = (_localWindowStart + 1) % NetConstants.MaxSequence;
}
//clear packet
if (_pendingPackets[pendingIdx].Clear(Peer))
NetDebug.Write("[PA]Removing reliableInOrder ack: {0} - true", pendingSeq);
}
}
}
protected override bool SendNextPackets()
{
if (_mustSendAcks)
{
_mustSendAcks = false;
NetDebug.Write("[RR]SendAcks");
lock(_outgoingAcks)
Peer.SendUserData(_outgoingAcks);
}
long currentTime = DateTime.UtcNow.Ticks;
bool hasPendingPackets = false;
lock (_pendingPackets)
{
//get packets from queue
lock (OutgoingQueue)
{
while (OutgoingQueue.Count > 0)
{
int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart);
if (relate >= _windowSize)
break;
var netPacket = OutgoingQueue.Dequeue();
netPacket.Sequence = (ushort) _localSeqence;
netPacket.ChannelId = _id;
_pendingPackets[_localSeqence % _windowSize].Init(netPacket);
_localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence;
}
}
//send
for (int pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
{
// Please note: TrySend is invoked on a mutable struct, it's important to not extract it into a variable here
bool hasPacket;
_pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer, out hasPacket);
if (hasPacket)
{
hasPendingPackets = true;
}
}
}
return hasPendingPackets || _mustSendAcks || OutgoingQueue.Count > 0;
}
//Process incoming packet
public override bool ProcessPacket(NetPacket packet)
{
if (packet.Property == PacketProperty.Ack)
{
ProcessAck(packet);
return false;
}
int seq = packet.Sequence;
if (seq >= NetConstants.MaxSequence)
{
NetDebug.Write("[RR]Bad sequence");
return false;
}
int relate = NetUtils.RelativeSequenceNumber(seq, _remoteWindowStart);
int relateSeq = NetUtils.RelativeSequenceNumber(seq, _remoteSequence);
if (relateSeq > _windowSize)
{
NetDebug.Write("[RR]Bad sequence");
return false;
}
//Drop bad packets
if (relate < 0)
{
//Too old packet doesn't ack
NetDebug.Write("[RR]ReliableInOrder too old");
return false;
}
if (relate >= _windowSize * 2)
{
//Some very new packet
NetDebug.Write("[RR]ReliableInOrder too new");
return false;
}
//If very new - move window
int ackIdx;
int ackByte;
int ackBit;
lock (_outgoingAcks)
{
if (relate >= _windowSize)
{
//New window position
int newWindowStart = (_remoteWindowStart + relate - _windowSize + 1) % NetConstants.MaxSequence;
_outgoingAcks.Sequence = (ushort) newWindowStart;
//Clean old data
while (_remoteWindowStart != newWindowStart)
{
ackIdx = _remoteWindowStart % _windowSize;
ackByte = NetConstants.ChanneledHeaderSize + ackIdx / BitsInByte;
ackBit = ackIdx % BitsInByte;
_outgoingAcks.RawData[ackByte] &= (byte) ~(1 << ackBit);
_remoteWindowStart = (_remoteWindowStart + 1) % NetConstants.MaxSequence;
}
}
//Final stage - process valid packet
//trigger acks send
_mustSendAcks = true;
ackIdx = seq % _windowSize;
ackByte = NetConstants.ChanneledHeaderSize + ackIdx / BitsInByte;
ackBit = ackIdx % BitsInByte;
if ((_outgoingAcks.RawData[ackByte] & (1 << ackBit)) != 0)
{
NetDebug.Write("[RR]ReliableInOrder duplicate");
return false;
}
//save ack
_outgoingAcks.RawData[ackByte] |= (byte) (1 << ackBit);
}
AddToPeerChannelSendQueue();
//detailed check
if (seq == _remoteSequence)
{
NetDebug.Write("[RR]ReliableInOrder packet succes");
Peer.AddReliablePacket(_deliveryMethod, packet);
_remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence;
if (_ordered)
{
NetPacket p;
while ((p = _receivedPackets[_remoteSequence % _windowSize]) != null)
{
//process holden packet
_receivedPackets[_remoteSequence % _windowSize] = null;
Peer.AddReliablePacket(_deliveryMethod, p);
_remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence;
}
}
else
{
while (_earlyReceived[_remoteSequence % _windowSize])
{
//process early packet
_earlyReceived[_remoteSequence % _windowSize] = false;
_remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence;
}
}
return true;
}
//holden packet
if (_ordered)
{
_receivedPackets[ackIdx] = packet;
}
else
{
_earlyReceived[ackIdx] = true;
Peer.AddReliablePacket(_deliveryMethod, packet);
}
return true;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 516bd901eb62f4bb391ef541f9effdec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,113 @@
using System;
namespace FlyingWormConsole3.LiteNetLib
{
internal sealed class SequencedChannel : BaseChannel
{
private int _localSequence;
private ushort _remoteSequence;
private readonly bool _reliable;
private NetPacket _lastPacket;
private readonly NetPacket _ackPacket;
private bool _mustSendAck;
private readonly byte _id;
private long _lastPacketSendTime;
public SequencedChannel(NetPeer peer, bool reliable, byte id) : base(peer)
{
_id = id;
_reliable = reliable;
if (_reliable)
_ackPacket = new NetPacket(PacketProperty.Ack, 0) {ChannelId = id};
}
protected override bool SendNextPackets()
{
if (_reliable && OutgoingQueue.Count == 0)
{
long currentTime = DateTime.UtcNow.Ticks;
long packetHoldTime = currentTime - _lastPacketSendTime;
if (packetHoldTime >= Peer.ResendDelay * TimeSpan.TicksPerMillisecond)
{
var packet = _lastPacket;
if (packet != null)
{
_lastPacketSendTime = currentTime;
Peer.SendUserData(packet);
}
}
}
else
{
lock (OutgoingQueue)
{
while (OutgoingQueue.Count > 0)
{
NetPacket packet = OutgoingQueue.Dequeue();
_localSequence = (_localSequence + 1) % NetConstants.MaxSequence;
packet.Sequence = (ushort)_localSequence;
packet.ChannelId = _id;
Peer.SendUserData(packet);
if (_reliable && OutgoingQueue.Count == 0)
{
_lastPacketSendTime = DateTime.UtcNow.Ticks;
_lastPacket = packet;
}
else
{
Peer.NetManager.NetPacketPool.Recycle(packet);
}
}
}
}
if (_reliable && _mustSendAck)
{
_mustSendAck = false;
_ackPacket.Sequence = _remoteSequence;
Peer.SendUserData(_ackPacket);
}
return _lastPacket != null;
}
public override bool ProcessPacket(NetPacket packet)
{
if (packet.IsFragmented)
return false;
if (packet.Property == PacketProperty.Ack)
{
if (_reliable && _lastPacket != null && packet.Sequence == _lastPacket.Sequence)
_lastPacket = null;
return false;
}
int relative = NetUtils.RelativeSequenceNumber(packet.Sequence, _remoteSequence);
bool packetProcessed = false;
if (packet.Sequence < NetConstants.MaxSequence && relative > 0)
{
if (Peer.NetManager.EnableStatistics)
{
Peer.Statistics.AddPacketLoss(relative - 1);
Peer.NetManager.Statistics.AddPacketLoss(relative - 1);
}
_remoteSequence = packet.Sequence;
Peer.NetManager.CreateReceiveEvent(
packet,
_reliable ? DeliveryMethod.ReliableSequenced : DeliveryMethod.Sequenced,
NetConstants.ChanneledHeaderSize,
Peer);
packetProcessed = true;
}
if (_reliable)
{
_mustSendAck = true;
AddToPeerChannelSendQueue();
}
return packetProcessed;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 84bbbc6c6e45c4287917fc944650e4af
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6b2625aef16274ccc89d570bf9e70c88
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,111 @@
#if NETCOREAPP3_0_OR_GREATER || NETCOREAPP3_1
using System;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.X86;
#endif
namespace FlyingWormConsole3.LiteNetLib.Utils
{
//Implementation from Crc32.NET
public static class CRC32C
{
public const int ChecksumSize = 4;
private const uint Poly = 0x82F63B78u;
private static readonly uint[] Table;
static CRC32C()
{
#if NETCOREAPP3_0_OR_GREATER || NETCOREAPP3_1
if(Sse42.IsSupported)
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;
}
}
}
/// <summary>
/// Compute CRC32C for data
/// </summary>
/// <param name="input">input data</param>
/// <param name="offset">offset</param>
/// <param name="length">length</param>
/// <returns>CRC32C checksum</returns>
public static uint Compute(byte[] input, int offset, int length)
{
uint crcLocal = uint.MaxValue;
#if NETCOREAPP3_0_OR_GREATER || NETCOREAPP3_1
if (Sse42.IsSupported)
{
var data = new ReadOnlySpan<byte>(input, offset, length);
int processed = 0;
if (Sse42.X64.IsSupported && data.Length > sizeof(ulong))
{
processed = data.Length / sizeof(ulong) * sizeof(ulong);
var ulongs = MemoryMarshal.Cast<byte, ulong>(data.Slice(0, processed));
ulong crclong = crcLocal;
for (int i = 0; i < ulongs.Length; i++)
{
crclong = Sse42.X64.Crc32(crclong, ulongs[i]);
}
crcLocal = (uint)crclong;
}
else if (data.Length > sizeof(uint))
{
processed = data.Length / sizeof(uint) * sizeof(uint);
var uints = MemoryMarshal.Cast<byte, uint>(data.Slice(0, processed));
for (int i = 0; i < uints.Length; i++)
{
crcLocal = Sse42.Crc32(crcLocal, uints[i]);
}
}
for (int i = processed; i < data.Length; i++)
{
crcLocal = Sse42.Crc32(crcLocal, data[i]);
}
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5ea151e8b0fce426e8025d63759d29a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,118 @@
using System.Runtime.InteropServices;
namespace FlyingWormConsole3.LiteNetLib.Utils
{
public static class FastBitConverter
{
[StructLayout(LayoutKind.Explicit)]
private struct ConverterHelperDouble
{
[FieldOffset(0)]
public ulong Along;
[FieldOffset(0)]
public double Adouble;
}
[StructLayout(LayoutKind.Explicit)]
private struct ConverterHelperFloat
{
[FieldOffset(0)]
public int Aint;
[FieldOffset(0)]
public float Afloat;
}
private static void WriteLittleEndian(byte[] buffer, int offset, ulong data)
{
#if BIGENDIAN
buffer[offset + 7] = (byte)(data);
buffer[offset + 6] = (byte)(data >> 8);
buffer[offset + 5] = (byte)(data >> 16);
buffer[offset + 4] = (byte)(data >> 24);
buffer[offset + 3] = (byte)(data >> 32);
buffer[offset + 2] = (byte)(data >> 40);
buffer[offset + 1] = (byte)(data >> 48);
buffer[offset ] = (byte)(data >> 56);
#else
buffer[offset] = (byte)(data);
buffer[offset + 1] = (byte)(data >> 8);
buffer[offset + 2] = (byte)(data >> 16);
buffer[offset + 3] = (byte)(data >> 24);
buffer[offset + 4] = (byte)(data >> 32);
buffer[offset + 5] = (byte)(data >> 40);
buffer[offset + 6] = (byte)(data >> 48);
buffer[offset + 7] = (byte)(data >> 56);
#endif
}
private static void WriteLittleEndian(byte[] buffer, int offset, int data)
{
#if BIGENDIAN
buffer[offset + 3] = (byte)(data);
buffer[offset + 2] = (byte)(data >> 8);
buffer[offset + 1] = (byte)(data >> 16);
buffer[offset ] = (byte)(data >> 24);
#else
buffer[offset] = (byte)(data);
buffer[offset + 1] = (byte)(data >> 8);
buffer[offset + 2] = (byte)(data >> 16);
buffer[offset + 3] = (byte)(data >> 24);
#endif
}
public static void WriteLittleEndian(byte[] buffer, int offset, short data)
{
#if BIGENDIAN
buffer[offset + 1] = (byte)(data);
buffer[offset ] = (byte)(data >> 8);
#else
buffer[offset] = (byte)(data);
buffer[offset + 1] = (byte)(data >> 8);
#endif
}
public static void GetBytes(byte[] bytes, int startIndex, double value)
{
ConverterHelperDouble ch = new ConverterHelperDouble { Adouble = value };
WriteLittleEndian(bytes, startIndex, ch.Along);
}
public static void GetBytes(byte[] bytes, int startIndex, float value)
{
ConverterHelperFloat ch = new ConverterHelperFloat { Afloat = value };
WriteLittleEndian(bytes, startIndex, ch.Aint);
}
public static void GetBytes(byte[] bytes, int startIndex, short value)
{
WriteLittleEndian(bytes, startIndex, value);
}
public static void GetBytes(byte[] bytes, int startIndex, ushort value)
{
WriteLittleEndian(bytes, startIndex, (short)value);
}
public static void GetBytes(byte[] bytes, int startIndex, int value)
{
WriteLittleEndian(bytes, startIndex, value);
}
public static void GetBytes(byte[] bytes, int startIndex, uint value)
{
WriteLittleEndian(bytes, startIndex, (int)value);
}
public static void GetBytes(byte[] bytes, int startIndex, long value)
{
WriteLittleEndian(bytes, startIndex, (ulong)value);
}
public static void GetBytes(byte[] bytes, int startIndex, ulong value)
{
WriteLittleEndian(bytes, startIndex, value);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13e65375234fb4dc8a9f5d2bedc0a9a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
namespace FlyingWormConsole3.LiteNetLib.Utils
{
public interface INetSerializable
{
void Serialize(NetDataWriter writer);
void Deserialize(NetDataReader reader);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c398145f81114a038e1d9c9982282f5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,694 @@
using System;
using System.Net;
using System.Text;
namespace FlyingWormConsole3.LiteNetLib.Utils
{
public class NetDataReader
{
protected byte[] _data;
protected int _position;
protected int _dataSize;
private int _offset;
public byte[] RawData
{
get { return _data; }
}
public int RawDataSize
{
get { return _dataSize; }
}
public int UserDataOffset
{
get { return _offset; }
}
public int UserDataSize
{
get { return _dataSize - _offset; }
}
public bool IsNull
{
get { return _data == null; }
}
public int Position
{
get { return _position; }
}
public bool EndOfData
{
get { return _position == _dataSize; }
}
public int AvailableBytes
{
get { return _dataSize - _position; }
}
public void SkipBytes(int count)
{
_position += count;
}
public void SetSource(NetDataWriter dataWriter)
{
_data = dataWriter.Data;
_position = 0;
_offset = 0;
_dataSize = dataWriter.Length;
}
public void SetSource(byte[] source)
{
_data = source;
_position = 0;
_offset = 0;
_dataSize = source.Length;
}
public void SetSource(byte[] source, int offset)
{
_data = source;
_position = offset;
_offset = offset;
_dataSize = source.Length;
}
public void SetSource(byte[] source, int offset, int maxSize)
{
_data = source;
_position = offset;
_offset = offset;
_dataSize = maxSize;
}
public NetDataReader()
{
}
public NetDataReader(NetDataWriter writer)
{
SetSource(writer);
}
public NetDataReader(byte[] source)
{
SetSource(source);
}
public NetDataReader(byte[] source, int offset)
{
SetSource(source, offset);
}
public NetDataReader(byte[] source, int offset, int maxSize)
{
SetSource(source, offset, maxSize);
}
#region GetMethods
public IPEndPoint GetNetEndPoint()
{
string host = GetString(1000);
int port = GetInt();
return NetUtils.MakeEndPoint(host, port);
}
public byte GetByte()
{
byte res = _data[_position];
_position += 1;
return res;
}
public sbyte GetSByte()
{
var b = (sbyte)_data[_position];
_position++;
return b;
}
public bool[] GetBoolArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new bool[size];
Buffer.BlockCopy(_data, _position, arr, 0, size);
_position += size;
return arr;
}
public ushort[] GetUShortArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new ushort[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 2);
_position += size * 2;
return arr;
}
public short[] GetShortArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new short[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 2);
_position += size * 2;
return arr;
}
public long[] GetLongArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new long[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 8);
_position += size * 8;
return arr;
}
public ulong[] GetULongArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new ulong[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 8);
_position += size * 8;
return arr;
}
public int[] GetIntArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new int[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 4);
_position += size * 4;
return arr;
}
public uint[] GetUIntArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new uint[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 4);
_position += size * 4;
return arr;
}
public float[] GetFloatArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new float[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 4);
_position += size * 4;
return arr;
}
public double[] GetDoubleArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new double[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 8);
_position += size * 8;
return arr;
}
public string[] GetStringArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new string[size];
for (int i = 0; i < size; i++)
{
arr[i] = GetString();
}
return arr;
}
public string[] GetStringArray(int maxStringLength)
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new string[size];
for (int i = 0; i < size; i++)
{
arr[i] = GetString(maxStringLength);
}
return arr;
}
public bool GetBool()
{
bool res = _data[_position] > 0;
_position += 1;
return res;
}
public char GetChar()
{
char result = BitConverter.ToChar(_data, _position);
_position += 2;
return result;
}
public ushort GetUShort()
{
ushort result = BitConverter.ToUInt16(_data, _position);
_position += 2;
return result;
}
public short GetShort()
{
short result = BitConverter.ToInt16(_data, _position);
_position += 2;
return result;
}
public long GetLong()
{
long result = BitConverter.ToInt64(_data, _position);
_position += 8;
return result;
}
public ulong GetULong()
{
ulong result = BitConverter.ToUInt64(_data, _position);
_position += 8;
return result;
}
public int GetInt()
{
int result = BitConverter.ToInt32(_data, _position);
_position += 4;
return result;
}
public uint GetUInt()
{
uint result = BitConverter.ToUInt32(_data, _position);
_position += 4;
return result;
}
public float GetFloat()
{
float result = BitConverter.ToSingle(_data, _position);
_position += 4;
return result;
}
public double GetDouble()
{
double result = BitConverter.ToDouble(_data, _position);
_position += 8;
return result;
}
public string GetString(int maxLength)
{
int bytesCount = GetInt();
if (bytesCount <= 0 || bytesCount > maxLength*2)
{
return string.Empty;
}
int charCount = Encoding.UTF8.GetCharCount(_data, _position, bytesCount);
if (charCount > maxLength)
{
return string.Empty;
}
string result = Encoding.UTF8.GetString(_data, _position, bytesCount);
_position += bytesCount;
return result;
}
public string GetString()
{
int bytesCount = GetInt();
if (bytesCount <= 0)
{
return string.Empty;
}
string result = Encoding.UTF8.GetString(_data, _position, bytesCount);
_position += bytesCount;
return result;
}
public ArraySegment<byte> GetRemainingBytesSegment()
{
ArraySegment<byte> segment = new ArraySegment<byte>(_data, _position, AvailableBytes);
_position = _data.Length;
return segment;
}
public T Get<T>() where T : INetSerializable, new()
{
var obj = new T();
obj.Deserialize(this);
return obj;
}
public byte[] GetRemainingBytes()
{
byte[] outgoingData = new byte[AvailableBytes];
Buffer.BlockCopy(_data, _position, outgoingData, 0, AvailableBytes);
_position = _data.Length;
return outgoingData;
}
public void GetBytes(byte[] destination, int start, int count)
{
Buffer.BlockCopy(_data, _position, destination, start, count);
_position += count;
}
public void GetBytes(byte[] destination, int count)
{
Buffer.BlockCopy(_data, _position, destination, 0, count);
_position += count;
}
public sbyte[] GetSBytesWithLength()
{
int length = GetInt();
sbyte[] outgoingData = new sbyte[length];
Buffer.BlockCopy(_data, _position, outgoingData, 0, length);
_position += length;
return outgoingData;
}
public byte[] GetBytesWithLength()
{
int length = GetInt();
byte[] outgoingData = new byte[length];
Buffer.BlockCopy(_data, _position, outgoingData, 0, length);
_position += length;
return outgoingData;
}
#endregion
#region PeekMethods
public byte PeekByte()
{
return _data[_position];
}
public sbyte PeekSByte()
{
return (sbyte)_data[_position];
}
public bool PeekBool()
{
return _data[_position] > 0;
}
public char PeekChar()
{
return BitConverter.ToChar(_data, _position);
}
public ushort PeekUShort()
{
return BitConverter.ToUInt16(_data, _position);
}
public short PeekShort()
{
return BitConverter.ToInt16(_data, _position);
}
public long PeekLong()
{
return BitConverter.ToInt64(_data, _position);
}
public ulong PeekULong()
{
return BitConverter.ToUInt64(_data, _position);
}
public int PeekInt()
{
return BitConverter.ToInt32(_data, _position);
}
public uint PeekUInt()
{
return BitConverter.ToUInt32(_data, _position);
}
public float PeekFloat()
{
return BitConverter.ToSingle(_data, _position);
}
public double PeekDouble()
{
return BitConverter.ToDouble(_data, _position);
}
public string PeekString(int maxLength)
{
int bytesCount = BitConverter.ToInt32(_data, _position);
if (bytesCount <= 0 || bytesCount > maxLength * 2)
{
return string.Empty;
}
int charCount = Encoding.UTF8.GetCharCount(_data, _position + 4, bytesCount);
if (charCount > maxLength)
{
return string.Empty;
}
string result = Encoding.UTF8.GetString(_data, _position + 4, bytesCount);
return result;
}
public string PeekString()
{
int bytesCount = BitConverter.ToInt32(_data, _position);
if (bytesCount <= 0)
{
return string.Empty;
}
string result = Encoding.UTF8.GetString(_data, _position + 4, bytesCount);
return result;
}
#endregion
#region TryGetMethods
public bool TryGetByte(out byte result)
{
if (AvailableBytes >= 1)
{
result = GetByte();
return true;
}
result = 0;
return false;
}
public bool TryGetSByte(out sbyte result)
{
if (AvailableBytes >= 1)
{
result = GetSByte();
return true;
}
result = 0;
return false;
}
public bool TryGetBool(out bool result)
{
if (AvailableBytes >= 1)
{
result = GetBool();
return true;
}
result = false;
return false;
}
public bool TryGetChar(out char result)
{
if (AvailableBytes >= 2)
{
result = GetChar();
return true;
}
result = '\0';
return false;
}
public bool TryGetShort(out short result)
{
if (AvailableBytes >= 2)
{
result = GetShort();
return true;
}
result = 0;
return false;
}
public bool TryGetUShort(out ushort result)
{
if (AvailableBytes >= 2)
{
result = GetUShort();
return true;
}
result = 0;
return false;
}
public bool TryGetInt(out int result)
{
if (AvailableBytes >= 4)
{
result = GetInt();
return true;
}
result = 0;
return false;
}
public bool TryGetUInt(out uint result)
{
if (AvailableBytes >= 4)
{
result = GetUInt();
return true;
}
result = 0;
return false;
}
public bool TryGetLong(out long result)
{
if (AvailableBytes >= 8)
{
result = GetLong();
return true;
}
result = 0;
return false;
}
public bool TryGetULong(out ulong result)
{
if (AvailableBytes >= 8)
{
result = GetULong();
return true;
}
result = 0;
return false;
}
public bool TryGetFloat(out float result)
{
if (AvailableBytes >= 4)
{
result = GetFloat();
return true;
}
result = 0;
return false;
}
public bool TryGetDouble(out double result)
{
if (AvailableBytes >= 8)
{
result = GetDouble();
return true;
}
result = 0;
return false;
}
public bool TryGetString(out string result)
{
if (AvailableBytes >= 4)
{
var bytesCount = PeekInt();
if (AvailableBytes >= bytesCount + 4)
{
result = GetString();
return true;
}
}
result = null;
return false;
}
public bool TryGetStringArray(out string[] result)
{
ushort size;
if (!TryGetUShort(out size))
{
result = null;
return false;
}
result = new string[size];
for (int i = 0; i < size; i++)
{
if (!TryGetString(out result[i]))
{
result = null;
return false;
}
}
return true;
}
public bool TryGetBytesWithLength(out byte[] result)
{
if (AvailableBytes >= 4)
{
var length = PeekInt();
if (length >= 0 && AvailableBytes >= length + 4)
{
result = GetBytesWithLength();
return true;
}
}
result = null;
return false;
}
#endregion
public void Clear()
{
_position = 0;
_dataSize = 0;
_data = null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f431ad5ab5fc45f6a3378f6aade1024
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,394 @@
using System;
using System.Net;
using System.Text;
namespace FlyingWormConsole3.LiteNetLib.Utils
{
public class NetDataWriter
{
protected byte[] _data;
protected int _position;
private const int InitialSize = 64;
private readonly bool _autoResize;
public int Capacity
{
get { return _data.Length; }
}
public NetDataWriter() : this(true, InitialSize)
{
}
public NetDataWriter(bool autoResize) : this(autoResize, InitialSize)
{
}
public NetDataWriter(bool autoResize, int initialSize)
{
_data = new byte[initialSize];
_autoResize = autoResize;
}
/// <summary>
/// Creates NetDataWriter from existing ByteArray
/// </summary>
/// <param name="bytes">Source byte array</param>
/// <param name="copy">Copy array to new location or use existing</param>
public static NetDataWriter FromBytes(byte[] bytes, bool copy)
{
if (copy)
{
var netDataWriter = new NetDataWriter(true, bytes.Length);
netDataWriter.Put(bytes);
return netDataWriter;
}
return new NetDataWriter(true, 0) {_data = bytes, _position = bytes.Length};
}
/// <summary>
/// Creates NetDataWriter from existing ByteArray (always copied data)
/// </summary>
/// <param name="bytes">Source byte array</param>
/// <param name="offset">Offset of array</param>
/// <param name="length">Length of array</param>
public static NetDataWriter FromBytes(byte[] bytes, int offset, int length)
{
var netDataWriter = new NetDataWriter(true, bytes.Length);
netDataWriter.Put(bytes, offset, length);
return netDataWriter;
}
public static NetDataWriter FromString(string value)
{
var netDataWriter = new NetDataWriter();
netDataWriter.Put(value);
return netDataWriter;
}
public void ResizeIfNeed(int newSize)
{
int len = _data.Length;
if (len < newSize)
{
while (len < newSize)
len *= 2;
Array.Resize(ref _data, len);
}
}
public void Reset(int size)
{
ResizeIfNeed(size);
_position = 0;
}
public void Reset()
{
_position = 0;
}
public byte[] CopyData()
{
byte[] resultData = new byte[_position];
Buffer.BlockCopy(_data, 0, resultData, 0, _position);
return resultData;
}
public byte[] Data
{
get { return _data; }
}
public int Length
{
get { return _position; }
}
/// <summary>
/// Sets position of NetDataWriter to rewrite previous values
/// </summary>
/// <param name="position">new byte position</param>
/// <returns>previous position of data writer</returns>
public int SetPosition(int position)
{
int prevPosition = _position;
_position = position;
return prevPosition;
}
public void Put(float value)
{
if (_autoResize)
ResizeIfNeed(_position + 4);
FastBitConverter.GetBytes(_data, _position, value);
_position += 4;
}
public void Put(double value)
{
if (_autoResize)
ResizeIfNeed(_position + 8);
FastBitConverter.GetBytes(_data, _position, value);
_position += 8;
}
public void Put(long value)
{
if (_autoResize)
ResizeIfNeed(_position + 8);
FastBitConverter.GetBytes(_data, _position, value);
_position += 8;
}
public void Put(ulong value)
{
if (_autoResize)
ResizeIfNeed(_position + 8);
FastBitConverter.GetBytes(_data, _position, value);
_position += 8;
}
public void Put(int value)
{
if (_autoResize)
ResizeIfNeed(_position + 4);
FastBitConverter.GetBytes(_data, _position, value);
_position += 4;
}
public void Put(uint value)
{
if (_autoResize)
ResizeIfNeed(_position + 4);
FastBitConverter.GetBytes(_data, _position, value);
_position += 4;
}
public void Put(char value)
{
if (_autoResize)
ResizeIfNeed(_position + 2);
FastBitConverter.GetBytes(_data, _position, value);
_position += 2;
}
public void Put(ushort value)
{
if (_autoResize)
ResizeIfNeed(_position + 2);
FastBitConverter.GetBytes(_data, _position, value);
_position += 2;
}
public void Put(short value)
{
if (_autoResize)
ResizeIfNeed(_position + 2);
FastBitConverter.GetBytes(_data, _position, value);
_position += 2;
}
public void Put(sbyte value)
{
if (_autoResize)
ResizeIfNeed(_position + 1);
_data[_position] = (byte)value;
_position++;
}
public void Put(byte value)
{
if (_autoResize)
ResizeIfNeed(_position + 1);
_data[_position] = value;
_position++;
}
public void Put(byte[] data, int offset, int length)
{
if (_autoResize)
ResizeIfNeed(_position + length);
Buffer.BlockCopy(data, offset, _data, _position, length);
_position += length;
}
public void Put(byte[] data)
{
if (_autoResize)
ResizeIfNeed(_position + data.Length);
Buffer.BlockCopy(data, 0, _data, _position, data.Length);
_position += data.Length;
}
public void PutSBytesWithLength(sbyte[] data, int offset, int length)
{
if (_autoResize)
ResizeIfNeed(_position + length + 4);
FastBitConverter.GetBytes(_data, _position, length);
Buffer.BlockCopy(data, offset, _data, _position + 4, length);
_position += length + 4;
}
public void PutSBytesWithLength(sbyte[] data)
{
if (_autoResize)
ResizeIfNeed(_position + data.Length + 4);
FastBitConverter.GetBytes(_data, _position, data.Length);
Buffer.BlockCopy(data, 0, _data, _position + 4, data.Length);
_position += data.Length + 4;
}
public void PutBytesWithLength(byte[] data, int offset, int length)
{
if (_autoResize)
ResizeIfNeed(_position + length + 4);
FastBitConverter.GetBytes(_data, _position, length);
Buffer.BlockCopy(data, offset, _data, _position + 4, length);
_position += length + 4;
}
public void PutBytesWithLength(byte[] data)
{
if (_autoResize)
ResizeIfNeed(_position + data.Length + 4);
FastBitConverter.GetBytes(_data, _position, data.Length);
Buffer.BlockCopy(data, 0, _data, _position + 4, data.Length);
_position += data.Length + 4;
}
public void Put(bool value)
{
if (_autoResize)
ResizeIfNeed(_position + 1);
_data[_position] = (byte)(value ? 1 : 0);
_position++;
}
private void PutArray(Array arr, int sz)
{
ushort length = arr == null ? (ushort) 0 : (ushort)arr.Length;
sz *= length;
if (_autoResize)
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)
{
PutArray(value, 8);
}
public void PutArray(long[] value)
{
PutArray(value, 8);
}
public void PutArray(ulong[] value)
{
PutArray(value, 8);
}
public void PutArray(int[] value)
{
PutArray(value, 4);
}
public void PutArray(uint[] value)
{
PutArray(value, 4);
}
public void PutArray(ushort[] value)
{
PutArray(value, 2);
}
public void PutArray(short[] value)
{
PutArray(value, 2);
}
public void PutArray(bool[] value)
{
PutArray(value, 1);
}
public void PutArray(string[] value)
{
ushort len = value == null ? (ushort)0 : (ushort)value.Length;
Put(len);
for (int i = 0; i < len; i++)
Put(value[i]);
}
public void PutArray(string[] value, int maxLength)
{
ushort len = value == null ? (ushort)0 : (ushort)value.Length;
Put(len);
for (int i = 0; i < len; i++)
Put(value[i], maxLength);
}
public void Put(IPEndPoint endPoint)
{
Put(endPoint.Address.ToString());
Put(endPoint.Port);
}
public void Put(string value)
{
if (string.IsNullOrEmpty(value))
{
Put(0);
return;
}
//put bytes count
int bytesCount = Encoding.UTF8.GetByteCount(value);
if (_autoResize)
ResizeIfNeed(_position + bytesCount + 4);
Put(bytesCount);
//put string
Encoding.UTF8.GetBytes(value, 0, value.Length, _data, _position);
_position += bytesCount;
}
public void Put(string value, int maxLength)
{
if (string.IsNullOrEmpty(value))
{
Put(0);
return;
}
int length = value.Length > maxLength ? maxLength : value.Length;
//calculate max count
int bytesCount = Encoding.UTF8.GetByteCount(value);
if (_autoResize)
ResizeIfNeed(_position + bytesCount + 4);
//put bytes count
Put(bytesCount);
//put string
Encoding.UTF8.GetBytes(value, 0, length, _data, _position);
_position += bytesCount;
}
public void Put<T>(T obj) where T : INetSerializable
{
obj.Serialize(this);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0579e5183db02475682da5bfde58f0d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,313 @@
using System;
using System.Collections.Generic;
namespace FlyingWormConsole3.LiteNetLib.Utils
{
public class NetPacketProcessor
{
private static class HashCache<T>
{
public static readonly ulong Id;
//FNV-1 64 bit hash
static HashCache()
{
ulong hash = 14695981039346656037UL; //offset
string typeName = typeof(T).ToString();
for (var i = 0; i < typeName.Length; i++)
{
hash ^= typeName[i];
hash *= 1099511628211UL; //prime
}
Id = hash;
}
}
protected delegate void SubscribeDelegate(NetDataReader reader, object userData);
private readonly NetSerializer _netSerializer;
private readonly Dictionary<ulong, SubscribeDelegate> _callbacks = new Dictionary<ulong, SubscribeDelegate>();
private readonly NetDataWriter _netDataWriter = new NetDataWriter();
public NetPacketProcessor()
{
_netSerializer = new NetSerializer();
}
public NetPacketProcessor(int maxStringLength)
{
_netSerializer = new NetSerializer(maxStringLength);
}
protected virtual ulong GetHash<T>()
{
return HashCache<T>.Id;
}
protected virtual SubscribeDelegate GetCallbackFromData(NetDataReader reader)
{
var hash = reader.GetULong();
SubscribeDelegate action;
if (!_callbacks.TryGetValue(hash, out action))
{
throw new ParseException("Undefined packet in NetDataReader");
}
return action;
}
protected virtual void WriteHash<T>(NetDataWriter writer)
{
writer.Put(GetHash<T>());
}
/// <summary>
/// Register nested property type
/// </summary>
/// <typeparam name="T">INetSerializable structure</typeparam>
public void RegisterNestedType<T>() where T : struct, INetSerializable
{
_netSerializer.RegisterNestedType<T>();
}
/// <summary>
/// Register nested property type
/// </summary>
/// <param name="writeDelegate"></param>
/// <param name="readDelegate"></param>
public void RegisterNestedType<T>(Action<NetDataWriter, T> writeDelegate, Func<NetDataReader, T> readDelegate)
{
_netSerializer.RegisterNestedType<T>(writeDelegate, readDelegate);
}
/// <summary>
/// Register nested property type
/// </summary>
/// <typeparam name="T">INetSerializable class</typeparam>
public void RegisterNestedType<T>(Func<T> constructor) where T : class, INetSerializable
{
_netSerializer.RegisterNestedType(constructor);
}
/// <summary>
/// Reads all available data from NetDataReader and calls OnReceive delegates
/// </summary>
/// <param name="reader">NetDataReader with packets data</param>
public void ReadAllPackets(NetDataReader reader)
{
while (reader.AvailableBytes > 0)
ReadPacket(reader);
}
/// <summary>
/// Reads all available data from NetDataReader and calls OnReceive delegates
/// </summary>
/// <param name="reader">NetDataReader with packets data</param>
/// <param name="userData">Argument that passed to OnReceivedEvent</param>
/// <exception cref="ParseException">Malformed packet</exception>
public void ReadAllPackets(NetDataReader reader, object userData)
{
while (reader.AvailableBytes > 0)
ReadPacket(reader, userData);
}
/// <summary>
/// Reads one packet from NetDataReader and calls OnReceive delegate
/// </summary>
/// <param name="reader">NetDataReader with packet</param>
/// <exception cref="ParseException">Malformed packet</exception>
public void ReadPacket(NetDataReader reader)
{
ReadPacket(reader, null);
}
public void Send<T>(NetPeer peer, T packet, DeliveryMethod options) where T : class, new()
{
_netDataWriter.Reset();
Write(_netDataWriter, packet);
peer.Send(_netDataWriter, options);
}
public void SendNetSerializable<T>(NetPeer peer, T packet, DeliveryMethod options) where T : INetSerializable
{
_netDataWriter.Reset();
WriteNetSerializable(_netDataWriter, packet);
peer.Send(_netDataWriter, options);
}
public void Send<T>(NetManager manager, T packet, DeliveryMethod options) where T : class, new()
{
_netDataWriter.Reset();
Write(_netDataWriter, packet);
manager.SendToAll(_netDataWriter, options);
}
public void SendNetSerializable<T>(NetManager manager, T packet, DeliveryMethod options) where T : INetSerializable
{
_netDataWriter.Reset();
WriteNetSerializable(_netDataWriter, packet);
manager.SendToAll(_netDataWriter, options);
}
public void Write<T>(NetDataWriter writer, T packet) where T : class, new()
{
WriteHash<T>(writer);
_netSerializer.Serialize(writer, packet);
}
public void WriteNetSerializable<T>(NetDataWriter writer, T packet) where T : INetSerializable
{
WriteHash<T>(writer);
packet.Serialize(writer);
}
public byte[] Write<T>(T packet) where T : class, new()
{
_netDataWriter.Reset();
WriteHash<T>(_netDataWriter);
_netSerializer.Serialize(_netDataWriter, packet);
return _netDataWriter.CopyData();
}
public byte[] WriteNetSerializable<T>(T packet) where T : INetSerializable
{
_netDataWriter.Reset();
WriteHash<T>(_netDataWriter);
packet.Serialize(_netDataWriter);
return _netDataWriter.CopyData();
}
/// <summary>
/// Reads one packet from NetDataReader and calls OnReceive delegate
/// </summary>
/// <param name="reader">NetDataReader with packet</param>
/// <param name="userData">Argument that passed to OnReceivedEvent</param>
/// <exception cref="ParseException">Malformed packet</exception>
public void ReadPacket(NetDataReader reader, object userData)
{
GetCallbackFromData(reader)(reader, userData);
}
/// <summary>
/// Register and subscribe to packet receive event
/// </summary>
/// <param name="onReceive">event that will be called when packet deserialized with ReadPacket method</param>
/// <param name="packetConstructor">Method that constructs packet instead of slow Activator.CreateInstance</param>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void Subscribe<T>(Action<T> onReceive, Func<T> packetConstructor) where T : class, new()
{
_netSerializer.Register<T>();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
var reference = packetConstructor();
_netSerializer.Deserialize(reader, reference);
onReceive(reference);
};
}
/// <summary>
/// Register and subscribe to packet receive event (with userData)
/// </summary>
/// <param name="onReceive">event that will be called when packet deserialized with ReadPacket method</param>
/// <param name="packetConstructor">Method that constructs packet instead of slow Activator.CreateInstance</param>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void Subscribe<T, TUserData>(Action<T, TUserData> onReceive, Func<T> packetConstructor) where T : class, new()
{
_netSerializer.Register<T>();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
var reference = packetConstructor();
_netSerializer.Deserialize(reader, reference);
onReceive(reference, (TUserData)userData);
};
}
/// <summary>
/// Register and subscribe to packet receive event
/// This method will overwrite last received packet class on receive (less garbage)
/// </summary>
/// <param name="onReceive">event that will be called when packet deserialized with ReadPacket method</param>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void SubscribeReusable<T>(Action<T> onReceive) where T : class, new()
{
_netSerializer.Register<T>();
var reference = new T();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
_netSerializer.Deserialize(reader, reference);
onReceive(reference);
};
}
/// <summary>
/// Register and subscribe to packet receive event
/// This method will overwrite last received packet class on receive (less garbage)
/// </summary>
/// <param name="onReceive">event that will be called when packet deserialized with ReadPacket method</param>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void SubscribeReusable<T, TUserData>(Action<T, TUserData> onReceive) where T : class, new()
{
_netSerializer.Register<T>();
var reference = new T();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
_netSerializer.Deserialize(reader, reference);
onReceive(reference, (TUserData)userData);
};
}
public void SubscribeNetSerializable<T, TUserData>(
Action<T, TUserData> onReceive,
Func<T> packetConstructor) where T : INetSerializable
{
_callbacks[GetHash<T>()] = (reader, userData) =>
{
var pkt = packetConstructor();
pkt.Deserialize(reader);
onReceive(pkt, (TUserData)userData);
};
}
public void SubscribeNetSerializable<T>(
Action<T> onReceive,
Func<T> packetConstructor) where T : INetSerializable
{
_callbacks[GetHash<T>()] = (reader, userData) =>
{
var pkt = packetConstructor();
pkt.Deserialize(reader);
onReceive(pkt);
};
}
public void SubscribeNetSerializable<T, TUserData>(
Action<T, TUserData> onReceive) where T : INetSerializable, new()
{
var reference = new T();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
reference.Deserialize(reader);
onReceive(reference, (TUserData)userData);
};
}
public void SubscribeNetSerializable<T>(
Action<T> onReceive) where T : INetSerializable, new()
{
var reference = new T();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
reference.Deserialize(reader);
onReceive(reference);
};
}
/// <summary>
/// Remove any subscriptions by type
/// </summary>
/// <typeparam name="T">Packet type</typeparam>
/// <returns>true if remove is success</returns>
public bool RemoveSubscription<T>()
{
return _callbacks.Remove(GetHash<T>());
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 482bf613849e6475493609e99056e557
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,747 @@
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Net;
using System.Runtime.Serialization;
namespace FlyingWormConsole3.LiteNetLib.Utils
{
public class InvalidTypeException : ArgumentException
{
public InvalidTypeException(string message) : base(message) { }
}
public class ParseException : Exception
{
public ParseException(string message) : base(message) { }
}
public class NetSerializer
{
private enum CallType
{
Basic,
Array,
List
}
private abstract class FastCall<T>
{
public CallType Type;
public virtual void Init(MethodInfo getMethod, MethodInfo setMethod, CallType type) { Type = type; }
public abstract void Read(T inf, NetDataReader r);
public abstract void Write(T inf, NetDataWriter w);
public abstract void ReadArray(T inf, NetDataReader r);
public abstract void WriteArray(T inf, NetDataWriter w);
public abstract void ReadList(T inf, NetDataReader r);
public abstract void WriteList(T inf, NetDataWriter w);
}
private abstract class FastCallSpecific<TClass, TProperty> : FastCall<TClass>
{
protected Func<TClass, TProperty> Getter;
protected Action<TClass, TProperty> Setter;
protected Func<TClass, TProperty[]> GetterArr;
protected Action<TClass, TProperty[]> SetterArr;
protected Func<TClass, List<TProperty>> GetterList;
protected Action<TClass, List<TProperty>> SetterList;
public override void ReadArray(TClass inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: " + typeof(TProperty) + "[]"); }
public override void WriteArray(TClass inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: " + typeof(TProperty) + "[]"); }
public override void ReadList(TClass inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: List<" + typeof(TProperty) + ">"); }
public override void WriteList(TClass inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: List<" + typeof(TProperty) + ">"); }
protected TProperty[] ReadArrayHelper(TClass inf, NetDataReader r)
{
ushort count = r.GetUShort();
var arr = GetterArr(inf);
arr = arr == null || arr.Length != count ? new TProperty[count] : arr;
SetterArr(inf, arr);
return arr;
}
protected TProperty[] WriteArrayHelper(TClass inf, NetDataWriter w)
{
var arr = GetterArr(inf);
w.Put((ushort)arr.Length);
return arr;
}
protected List<TProperty> ReadListHelper(TClass inf, NetDataReader r, out int len)
{
len = r.GetUShort();
var list = GetterList(inf);
if (list == null)
{
list = new List<TProperty>(len);
SetterList(inf, list);
}
return list;
}
protected List<TProperty> WriteListHelper(TClass inf, NetDataWriter w, out int len)
{
var list = GetterList(inf);
if (list == null)
{
len = 0;
w.Put(0);
return null;
}
len = list.Count;
w.Put((ushort)len);
return list;
}
public override void Init(MethodInfo getMethod, MethodInfo setMethod, CallType type)
{
base.Init(getMethod, setMethod, type);
switch (type)
{
case CallType.Array:
GetterArr = (Func<TClass, TProperty[]>)Delegate.CreateDelegate(typeof(Func<TClass, TProperty[]>), getMethod);
SetterArr = (Action<TClass, TProperty[]>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty[]>), setMethod);
break;
case CallType.List:
GetterList = (Func<TClass, List<TProperty>>)Delegate.CreateDelegate(typeof(Func<TClass, List<TProperty>>), getMethod);
SetterList = (Action<TClass, List<TProperty>>)Delegate.CreateDelegate(typeof(Action<TClass, List<TProperty>>), setMethod);
break;
default:
Getter = (Func<TClass, TProperty>)Delegate.CreateDelegate(typeof(Func<TClass, TProperty>), getMethod);
Setter = (Action<TClass, TProperty>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty>), setMethod);
break;
}
}
}
private abstract class FastCallSpecificAuto<TClass, TProperty> : FastCallSpecific<TClass, TProperty>
{
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]);
}
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<TClass, TProperty> : FastCallSpecific<TClass, TProperty>
{
private readonly Action<NetDataWriter, TProperty> _writer;
private readonly Func<NetDataReader, TProperty> _reader;
public FastCallStatic(Action<NetDataWriter, TProperty> write, Func<NetDataReader, TProperty> 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 ReadList(TClass inf, NetDataReader r)
{
int len;
var list = ReadListHelper(inf, r, out len);
int listCount = list.Count;
for (int i = 0; i < len; i++)
{
if (i < listCount)
list[i] = _reader(r);
else
list.Add(_reader(r));
}
if (len < listCount)
list.RemoveRange(len, listCount - len);
}
public override void WriteList(TClass inf, NetDataWriter w)
{
int len;
var list = WriteListHelper(inf, w, out len);
for (int i = 0; i < len; i++)
_writer(w, list[i]);
}
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);
}
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<TClass, TProperty> : FastCallSpecific<TClass, TProperty> 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 ReadList(TClass inf, NetDataReader r)
{
int len;
var list = ReadListHelper(inf, r, out len);
int listCount = list.Count;
for (int i = 0; i < len; i++)
{
var itm = default(TProperty);
itm.Deserialize(r);
if(i < listCount)
list[i] = itm;
else
list.Add(itm);
}
if (len < listCount)
list.RemoveRange(len, listCount - len);
}
public override void WriteList(TClass inf, NetDataWriter w)
{
int len;
var list = WriteListHelper(inf, w, out len);
for (int i = 0; i < len; i++)
list[i].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);
}
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<TClass, TProperty> : FastCallSpecific<TClass, TProperty> where TProperty : class, INetSerializable
{
private readonly Func<TProperty> _constructor;
public FastCallClass(Func<TProperty> 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 ReadList(TClass inf, NetDataReader r)
{
int len;
var list = ReadListHelper(inf, r, out len);
int listCount = list.Count;
for (int i = 0; i < len; i++)
{
if (i < listCount)
{
list[i].Deserialize(r);
}
else
{
var itm = _constructor();
itm.Deserialize(r);
list.Add(itm);
}
}
if (len < listCount)
list.RemoveRange(len, listCount - len);
}
public override void WriteList(TClass inf, NetDataWriter w)
{
int len;
var list = WriteListHelper(inf, w, out len);
for (int i = 0; i < len; i++)
list[i].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);
}
}
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<T> : FastCallSpecific<T, int>
{
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)); }
}
private class UIntSerializer<T> : FastCallSpecific<T, uint>
{
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)); }
}
private class ShortSerializer<T> : FastCallSpecific<T, short>
{
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)); }
}
private class UShortSerializer<T> : FastCallSpecific<T, ushort>
{
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)); }
}
private class LongSerializer<T> : FastCallSpecific<T, long>
{
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)); }
}
private class ULongSerializer<T> : FastCallSpecific<T, ulong>
{
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)); }
}
private class ByteSerializer<T> : FastCallSpecific<T, byte>
{
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)); }
}
private class SByteSerializer<T> : FastCallSpecific<T, sbyte>
{
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)); }
}
private class FloatSerializer<T> : FastCallSpecific<T, float>
{
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<T> : FastCallSpecific<T, double>
{
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<T> : FastCallSpecific<T, bool>
{
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<T> : FastCallSpecificAuto<T, char>
{
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<T> : FastCallSpecificAuto<T, IPEndPoint>
{
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<T> : FastCallSpecific<T, string>
{
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); }
}
private class EnumByteSerializer<T> : FastCall<T>
{
protected readonly PropertyInfo Property;
protected readonly Type PropertyType;
public EnumByteSerializer(PropertyInfo property, Type propertyType)
{
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)); }
public override void ReadArray(T inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: Enum[]"); }
public override void WriteArray(T inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: Enum[]"); }
public override void ReadList(T inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: List<Enum>"); }
public override void WriteList(T inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: List<Enum>"); }
}
private class EnumIntSerializer<T> : EnumByteSerializer<T>
{
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<T>
{
public static ClassInfo<T> Instance;
private readonly FastCall<T>[] _serializers;
private readonly int _membersCount;
public ClassInfo(List<FastCall<T>> serializers)
{
_membersCount = serializers.Count;
_serializers = serializers.ToArray();
}
public void Write(T obj, NetDataWriter writer)
{
for (int i = 0; i < _membersCount; i++)
{
var s = _serializers[i];
if (s.Type == CallType.Basic)
s.Write(obj, writer);
else if (s.Type == CallType.Array)
s.WriteArray(obj, writer);
else
s.WriteList(obj, writer);
}
}
public void Read(T obj, NetDataReader reader)
{
for (int i = 0; i < _membersCount; i++)
{
var s = _serializers[i];
if (s.Type == CallType.Basic)
s.Read(obj, reader);
else if(s.Type == CallType.Array)
s.ReadArray(obj, reader);
else
s.ReadList(obj, reader);
}
}
}
private abstract class CustomType
{
public abstract FastCall<T> Get<T>();
}
private sealed class CustomTypeStruct<TProperty> : CustomType where TProperty : struct, INetSerializable
{
public override FastCall<T> Get<T>() { return new FastCallStruct<T, TProperty>(); }
}
private sealed class CustomTypeClass<TProperty> : CustomType where TProperty : class, INetSerializable
{
private readonly Func<TProperty> _constructor;
public CustomTypeClass(Func<TProperty> constructor) { _constructor = constructor; }
public override FastCall<T> Get<T>() { return new FastCallClass<T, TProperty>(_constructor); }
}
private sealed class CustomTypeStatic<TProperty> : CustomType
{
private readonly Action<NetDataWriter, TProperty> _writer;
private readonly Func<NetDataReader, TProperty> _reader;
public CustomTypeStatic(Action<NetDataWriter, TProperty> writer, Func<NetDataReader, TProperty> reader)
{
_writer = writer;
_reader = reader;
}
public override FastCall<T> Get<T>() { return new FastCallStatic<T, TProperty>(_writer, _reader); }
}
/// <summary>
/// Register custom property type
/// </summary>
/// <typeparam name="T">INetSerializable structure</typeparam>
public void RegisterNestedType<T>() where T : struct, INetSerializable
{
_registeredTypes.Add(typeof(T), new CustomTypeStruct<T>());
}
/// <summary>
/// Register custom property type
/// </summary>
/// <typeparam name="T">INetSerializable class</typeparam>
public void RegisterNestedType<T>(Func<T> constructor) where T : class, INetSerializable
{
_registeredTypes.Add(typeof(T), new CustomTypeClass<T>(constructor));
}
/// <summary>
/// Register custom property type
/// </summary>
/// <typeparam name="T">Any packet</typeparam>
/// <param name="writer">custom type writer</param>
/// <param name="reader">custom type reader</param>
public void RegisterNestedType<T>(Action<NetDataWriter, T> writer, Func<NetDataReader, T> reader)
{
_registeredTypes.Add(typeof(T), new CustomTypeStatic<T>(writer, reader));
}
private NetDataWriter _writer;
private readonly int _maxStringLength;
private readonly Dictionary<Type, CustomType> _registeredTypes = new Dictionary<Type, CustomType>();
public NetSerializer() : this(0)
{
}
public NetSerializer(int maxStringLength)
{
_maxStringLength = maxStringLength;
}
private ClassInfo<T> RegisterInternal<T>()
{
if (ClassInfo<T>.Instance != null)
return ClassInfo<T>.Instance;
Type t = typeof(T);
var props = t.GetProperties(
BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.GetProperty |
BindingFlags.SetProperty);
var serializers = new List<FastCall<T>>();
for (int i = 0; i < props.Length; i++)
{
var property = props[i];
var propertyType = property.PropertyType;
var elementType = propertyType.IsArray ? propertyType.GetElementType() : propertyType;
var callType = propertyType.IsArray ? CallType.Array : CallType.Basic;
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>))
{
elementType = propertyType.GetGenericArguments()[0];
callType = CallType.List;
}
// if (Attribute.IsDefined(property, typeof(IgnoreDataMemberAttribute)))
// continue;
var getMethod = property.GetGetMethod();
var setMethod = property.GetSetMethod();
if (getMethod == null || setMethod == null)
continue;
FastCall<T> serialzer = null;
if (propertyType.IsEnum)
{
var underlyingType = Enum.GetUnderlyingType(propertyType);
if (underlyingType == typeof(byte))
serialzer = new EnumByteSerializer<T>(property, propertyType);
else if (underlyingType == typeof(int))
serialzer = new EnumIntSerializer<T>(property, propertyType);
else
throw new InvalidTypeException("Not supported enum underlying type: " + underlyingType.Name);
}
else if (elementType == typeof(string))
serialzer = new StringSerializer<T>(_maxStringLength);
else if (elementType == typeof(bool))
serialzer = new BoolSerializer<T>();
else if (elementType == typeof(byte))
serialzer = new ByteSerializer<T>();
else if (elementType == typeof(sbyte))
serialzer = new SByteSerializer<T>();
else if (elementType == typeof(short))
serialzer = new ShortSerializer<T>();
else if (elementType == typeof(ushort))
serialzer = new UShortSerializer<T>();
else if (elementType == typeof(int))
serialzer = new IntSerializer<T>();
else if (elementType == typeof(uint))
serialzer = new UIntSerializer<T>();
else if (elementType == typeof(long))
serialzer = new LongSerializer<T>();
else if (elementType == typeof(ulong))
serialzer = new ULongSerializer<T>();
else if (elementType == typeof(float))
serialzer = new FloatSerializer<T>();
else if (elementType == typeof(double))
serialzer = new DoubleSerializer<T>();
else if (elementType == typeof(char))
serialzer = new CharSerializer<T>();
else if (elementType == typeof(IPEndPoint))
serialzer = new IPEndPointSerializer<T>();
else
{
CustomType customType;
_registeredTypes.TryGetValue(elementType, out customType);
if (customType != null)
serialzer = customType.Get<T>();
}
if (serialzer != null)
{
serialzer.Init(getMethod, setMethod, callType);
serializers.Add(serialzer);
}
else
{
throw new InvalidTypeException("Unknown property type: " + propertyType.FullName);
}
}
ClassInfo<T>.Instance = new ClassInfo<T>(serializers);
return ClassInfo<T>.Instance;
}
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void Register<T>()
{
RegisterInternal<T>();
}
/// <summary>
/// Reads packet with known type
/// </summary>
/// <param name="reader">NetDataReader with packet</param>
/// <returns>Returns packet if packet in reader is matched type</returns>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public T Deserialize<T>(NetDataReader reader) where T : class, new()
{
var info = RegisterInternal<T>();
var result = new T();
try
{
info.Read(result, reader);
}
catch
{
return null;
}
return result;
}
/// <summary>
/// Reads packet with known type (non alloc variant)
/// </summary>
/// <param name="reader">NetDataReader with packet</param>
/// <param name="target">Deserialization target</param>
/// <returns>Returns true if packet in reader is matched type</returns>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public bool Deserialize<T>(NetDataReader reader, T target) where T : class, new()
{
var info = RegisterInternal<T>();
try
{
info.Read(target, reader);
}
catch
{
return false;
}
return true;
}
/// <summary>
/// Serialize object to NetDataWriter (fast)
/// </summary>
/// <param name="writer">Serialization target NetDataWriter</param>
/// <param name="obj">Object to serialize</param>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void Serialize<T>(NetDataWriter writer, T obj) where T : class, new()
{
RegisterInternal<T>().Write(obj, writer);
}
/// <summary>
/// Serialize object to byte array
/// </summary>
/// <param name="obj">Object to serialize</param>
/// <returns>byte array with serialized data</returns>
public byte[] Serialize<T>(T obj) where T : class, new()
{
if (_writer == null)
_writer = new NetDataWriter();
_writer.Reset();
Serialize(_writer, obj);
return _writer.CopyData();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5f028b0f6ea44a118a7e3a9bb45108c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,426 @@
using System;
namespace FlyingWormConsole3.LiteNetLib.Utils
{
/// <summary>
/// Represents RFC4330 SNTP packet used for communication to and from a network time server.
/// </summary>
/// <remarks>
/// <para>
/// Most applications should just use the <see cref="NtpPacket.CorrectionOffset" /> property.
/// </para>
/// <para>
/// The same data structure represents both request and reply packets.
/// Request and reply differ in which properties are set and to what values.
/// </para>
/// <para>
/// The only real property is <see cref="NtpPacket.Bytes" />.
/// All other properties read from and write to the underlying byte array
/// with the exception of <see cref="NtpPacket.DestinationTimestamp" />,
/// which is not part of the packet on network and it is instead set locally after receiving the packet.
/// </para>
/// <para>
/// Copied from <a href="https://guerrillantp.machinezoo.com/">GuerrillaNtp project</a>
/// with permission from Robert Vazan (@robertvazan) under MIT license, see https://github.com/RevenantX/LiteNetLib/pull/236
/// </para>
/// </remarks>
public class NtpPacket
{
private static readonly DateTime Epoch = new DateTime(1900, 1, 1);
/// <summary>
/// Gets RFC4330-encoded SNTP packet.
/// </summary>
/// <value>
/// Byte array containing RFC4330-encoded SNTP packet. It is at least 48 bytes long.
/// </value>
/// <remarks>
/// This is the only real property. All other properties except
/// <see cref="NtpPacket.DestinationTimestamp" /> read from or write to this byte array.
/// </remarks>
public byte[] Bytes { get; private set; }
/// <summary>
/// Gets the leap second indicator.
/// </summary>
/// <value>
/// Leap second warning, if any. Special value
/// <see cref="NtpLeapIndicator.AlarmCondition" /> indicates unsynchronized server clock.
/// Default is <see cref="NtpLeapIndicator.NoWarning" />.
/// </value>
/// <remarks>
/// Only servers fill in this property. Clients can consult this property for possible leap second warning.
/// </remarks>
public NtpLeapIndicator LeapIndicator
{
get { return (NtpLeapIndicator)((Bytes[0] & 0xC0) >> 6); }
}
/// <summary>
/// Gets or sets protocol version number.
/// </summary>
/// <value>
/// SNTP protocol version. Default is 4, which is the latest version at the time of this writing.
/// </value>
/// <remarks>
/// In request packets, clients should leave this property at default value 4.
/// Servers usually reply with the same protocol version.
/// </remarks>
public int VersionNumber
{
get { return (Bytes[0] & 0x38) >> 3; }
private set { Bytes[0] = (byte)((Bytes[0] & ~0x38) | value << 3); }
}
/// <summary>
/// Gets or sets SNTP packet mode, i.e. whether this is client or server packet.
/// </summary>
/// <value>
/// SNTP packet mode. Default is <see cref="NtpMode.Client" /> in newly created packets.
/// Server reply should have this property set to <see cref="NtpMode.Server" />.
/// </value>
public NtpMode Mode
{
get { return (NtpMode)(Bytes[0] & 0x07); }
private set { Bytes[0] = (byte)((Bytes[0] & ~0x07) | (int)value); }
}
/// <summary>
/// Gets server's distance from the reference clock.
/// </summary>
/// <value>
/// <para>
/// Distance from the reference clock. This property is set only in server reply packets.
/// Servers connected directly to reference clock hardware set this property to 1.
/// Statum number is incremented by 1 on every hop down the NTP server hierarchy.
/// </para>
/// <para>
/// Special value 0 indicates that this packet is a Kiss-o'-Death message
/// with kiss code stored in <see cref="NtpPacket.ReferenceId" />.
/// </para>
/// </value>
public int Stratum { get { return Bytes[1]; } }
/// <summary>
/// Gets server's preferred polling interval.
/// </summary>
/// <value>
/// Polling interval in log2 seconds, e.g. 4 stands for 16s and 17 means 131,072s.
/// </value>
public int Poll { get { return Bytes[2]; } }
/// <summary>
/// Gets the precision of server clock.
/// </summary>
/// <value>
/// Clock precision in log2 seconds, e.g. -20 for microsecond precision.
/// </value>
public int Precision { get { return (sbyte)Bytes[3]; } }
/// <summary>
/// Gets the total round-trip delay from the server to the reference clock.
/// </summary>
/// <value>
/// Round-trip delay to the reference clock. Normally a positive value smaller than one second.
/// </value>
public TimeSpan RootDelay { get { return GetTimeSpan32(4); } }
/// <summary>
/// Gets the estimated error in time reported by the server.
/// </summary>
/// <value>
/// Estimated error in time reported by the server. Normally a positive value smaller than one second.
/// </value>
public TimeSpan RootDispersion { get { return GetTimeSpan32(8); } }
/// <summary>
/// Gets the ID of the time source used by the server or Kiss-o'-Death code sent by the server.
/// </summary>
/// <value>
/// <para>
/// ID of server's time source or Kiss-o'-Death code.
/// Purpose of this property depends on value of <see cref="NtpPacket.Stratum" /> property.
/// </para>
/// <para>
/// Stratum 1 servers write here one of several special values that describe the kind of hardware clock they use.
/// </para>
/// <para>
/// Stratum 2 and lower servers set this property to IPv4 address of their upstream server.
/// If upstream server has IPv6 address, the address is hashed, because it doesn't fit in this property.
/// </para>
/// <para>
/// When server sets <see cref="NtpPacket.Stratum" /> to special value 0,
/// this property contains so called kiss code that instructs the client to stop querying the server.
/// </para>
/// </value>
public uint ReferenceId { get { return GetUInt32BE(12); } }
/// <summary>
/// Gets or sets the time when the server clock was last set or corrected.
/// </summary>
/// <value>
/// Time when the server clock was last set or corrected or <c>null</c> when not specified.
/// </value>
/// <remarks>
/// This Property is usually set only by servers. It usually lags server's current time by several minutes,
/// so don't use this property for time synchronization.
/// </remarks>
public DateTime? ReferenceTimestamp { get { return GetDateTime64(16); } }
/// <summary>
/// Gets or sets the time when the client sent its request.
/// </summary>
/// <value>
/// This property is <c>null</c> in request packets.
/// In reply packets, it is the time when the client sent its request.
/// Servers copy this value from <see cref="NtpPacket.TransmitTimestamp" />
/// that they find in received request packet.
/// </value>
/// <seealso cref="NtpPacket.CorrectionOffset" />
/// <seealso cref="NtpPacket.RoundTripTime" />
public DateTime? OriginTimestamp { get { return GetDateTime64(24); } }
/// <summary>
/// Gets or sets the time when the request was received by the server.
/// </summary>
/// <value>
/// This property is <c>null</c> in request packets.
/// In reply packets, it is the time when the server received client request.
/// </value>
/// <seealso cref="NtpPacket.CorrectionOffset" />
/// <seealso cref="NtpPacket.RoundTripTime" />
public DateTime? ReceiveTimestamp { get { return GetDateTime64(32); } }
/// <summary>
/// Gets or sets the time when the packet was sent.
/// </summary>
/// <value>
/// Time when the packet was sent. It should never be <c>null</c>.
/// Default value is <see cref="System.DateTime.UtcNow" />.
/// </value>
/// <remarks>
/// This property must be set by both clients and servers.
/// </remarks>
/// <seealso cref="NtpPacket.CorrectionOffset" />
/// <seealso cref="NtpPacket.RoundTripTime" />
public DateTime? TransmitTimestamp { get { return GetDateTime64(40); } private set { SetDateTime64(40, value); } }
/// <summary>
/// Gets or sets the time of reception of response SNTP packet on the client.
/// </summary>
/// <value>
/// Time of reception of response SNTP packet on the client. It is <c>null</c> in request packets.
/// </value>
/// <remarks>
/// This property is not part of the protocol and has to be set when reply packet is received.
/// </remarks>
/// <seealso cref="NtpPacket.CorrectionOffset" />
/// <seealso cref="NtpPacket.RoundTripTime" />
public DateTime? DestinationTimestamp { get; private set; }
/// <summary>
/// Gets the round-trip time to the server.
/// </summary>
/// <value>
/// Time the request spent traveling to the server plus the time the reply spent traveling back.
/// This is calculated from timestamps in the packet as <c>(t1 - t0) + (t3 - t2)</c>
/// where t0 is <see cref="NtpPacket.OriginTimestamp" />,
/// t1 is <see cref="NtpPacket.ReceiveTimestamp" />,
/// t2 is <see cref="NtpPacket.TransmitTimestamp" />,
/// and t3 is <see cref="NtpPacket.DestinationTimestamp" />.
/// This property throws an exception in request packets.
/// </value>
public TimeSpan RoundTripTime
{
get
{
CheckTimestamps();
return (ReceiveTimestamp.Value - OriginTimestamp.Value) + (DestinationTimestamp.Value - TransmitTimestamp.Value);
}
}
/// <summary>
/// Gets the offset that should be added to local time to synchronize it with server time.
/// </summary>
/// <value>
/// Time difference between server and client. It should be added to local time to get server time.
/// It is calculated from timestamps in the packet as <c>0.5 * ((t1 - t0) - (t3 - t2))</c>
/// where t0 is <see cref="NtpPacket.OriginTimestamp" />,
/// t1 is <see cref="NtpPacket.ReceiveTimestamp" />,
/// t2 is <see cref="NtpPacket.TransmitTimestamp" />,
/// and t3 is <see cref="NtpPacket.DestinationTimestamp" />.
/// This property throws an exception in request packets.
/// </value>
public TimeSpan CorrectionOffset
{
get
{
CheckTimestamps();
return TimeSpan.FromTicks(((ReceiveTimestamp.Value - OriginTimestamp.Value) - (DestinationTimestamp.Value - TransmitTimestamp.Value)).Ticks / 2);
}
}
/// <summary>
/// Initializes default request packet.
/// </summary>
/// <remarks>
/// Properties <see cref="NtpPacket.Mode" /> and <see cref="NtpPacket.VersionNumber" />
/// are set appropriately for request packet. Property <see cref="NtpPacket.TransmitTimestamp" />
/// is set to <see cref="System.DateTime.UtcNow" />.
/// </remarks>
public NtpPacket() : this(new byte[48])
{
Mode = NtpMode.Client;
VersionNumber = 4;
TransmitTimestamp = DateTime.UtcNow;
}
/// <summary>
/// Initializes packet from received data.
/// </summary>
internal NtpPacket(byte[] bytes)
{
if (bytes.Length < 48)
throw new ArgumentException("SNTP reply packet must be at least 48 bytes long.", "bytes");
Bytes = bytes;
}
/// <summary>
/// Initializes packet from data received from a server.
/// </summary>
/// <param name="bytes">Data received from the server.</param>
/// <param name="destinationTimestamp">Utc time of reception of response SNTP packet on the client.</param>
/// <returns></returns>
public static NtpPacket FromServerResponse(byte[] bytes, DateTime destinationTimestamp)
{
return new NtpPacket(bytes) { DestinationTimestamp = destinationTimestamp };
}
internal void ValidateRequest()
{
if (Mode != NtpMode.Client)
throw new InvalidOperationException("This is not a request SNTP packet.");
if (VersionNumber == 0)
throw new InvalidOperationException("Protocol version of the request is not specified.");
if (TransmitTimestamp == null)
throw new InvalidOperationException("TransmitTimestamp must be set in request packet.");
}
internal void ValidateReply()
{
if (Mode != NtpMode.Server)
throw new InvalidOperationException("This is not a reply SNTP packet.");
if (VersionNumber == 0)
throw new InvalidOperationException("Protocol version of the reply is not specified.");
if (Stratum == 0)
throw new InvalidOperationException(string.Format("Received Kiss-o'-Death SNTP packet with code 0x{0:x}.", ReferenceId));
if (LeapIndicator == NtpLeapIndicator.AlarmCondition)
throw new InvalidOperationException("SNTP server has unsynchronized clock.");
CheckTimestamps();
}
private void CheckTimestamps()
{
if (OriginTimestamp == null)
throw new InvalidOperationException("Origin timestamp is missing.");
if (ReceiveTimestamp == null)
throw new InvalidOperationException("Receive timestamp is missing.");
if (TransmitTimestamp == null)
throw new InvalidOperationException("Transmit timestamp is missing.");
if (DestinationTimestamp == null)
throw new InvalidOperationException("Destination timestamp is missing.");
}
private DateTime? GetDateTime64(int offset)
{
var field = GetUInt64BE(offset);
if (field == 0)
return null;
return new DateTime(Epoch.Ticks + Convert.ToInt64(field * (1.0 / (1L << 32) * 10000000.0)));
}
private void SetDateTime64(int offset, DateTime? value)
{
SetUInt64BE(offset, value == null ? 0 : Convert.ToUInt64((value.Value.Ticks - Epoch.Ticks) * (0.0000001 * (1L << 32))));
}
private TimeSpan GetTimeSpan32(int offset)
{
return TimeSpan.FromSeconds(GetInt32BE(offset) / (double)(1 << 16));
}
private ulong GetUInt64BE(int offset)
{
return SwapEndianness(BitConverter.ToUInt64(Bytes, offset));
}
private void SetUInt64BE(int offset, ulong value)
{
FastBitConverter.GetBytes(Bytes, offset, SwapEndianness(value));
}
private int GetInt32BE(int offset)
{
return (int)GetUInt32BE(offset);
}
private uint GetUInt32BE(int offset)
{
return SwapEndianness(BitConverter.ToUInt32(Bytes, offset));
}
private static uint SwapEndianness(uint x)
{
return ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24);
}
private static ulong SwapEndianness(ulong x)
{
return ((ulong)SwapEndianness((uint)x) << 32) | SwapEndianness((uint)(x >> 32));
}
}
/// <summary>
/// Represents leap second warning from the server that instructs the client to add or remove leap second.
/// </summary>
/// <seealso cref="NtpPacket.LeapIndicator" />
public enum NtpLeapIndicator
{
/// <summary>
/// No leap second warning. No action required.
/// </summary>
NoWarning,
/// <summary>
/// Warns the client that the last minute of the current day has 61 seconds.
/// </summary>
LastMinuteHas61Seconds,
/// <summary>
/// Warns the client that the last minute of the current day has 59 seconds.
/// </summary>
LastMinuteHas59Seconds,
/// <summary>
/// Special value indicating that the server clock is unsynchronized and the returned time is unreliable.
/// </summary>
AlarmCondition
}
/// <summary>
/// Describes SNTP packet mode, i.e. client or server.
/// </summary>
/// <seealso cref="NtpPacket.Mode" />
public enum NtpMode
{
/// <summary>
/// Identifies client-to-server SNTP packet.
/// </summary>
Client = 3,
/// <summary>
/// Identifies server-to-client SNTP packet.
/// </summary>
Server = 4,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d047981f04958451890899788068ae9c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
using System.Net;
using System.Net.Sockets;
namespace FlyingWormConsole3.LiteNetLib.Utils
{
internal sealed class NtpRequest
{
private const int ResendTimer = 1000;
private const int KillTimer = 10000;
public const int DefaultPort = 123;
private readonly IPEndPoint _ntpEndPoint;
private int _resendTime = ResendTimer;
private int _killTime = 0;
public NtpRequest(IPEndPoint endPoint)
{
_ntpEndPoint = endPoint;
}
public bool NeedToKill
{
get { return _killTime >= KillTimer; }
}
public bool Send(NetSocket socket, int time)
{
_resendTime += time;
_killTime += time;
if (_resendTime < ResendTimer)
{
return false;
}
SocketError errorCode = 0;
var packet = new NtpPacket();
var sendCount = socket.SendTo(packet.Bytes, 0, packet.Bytes.Length, _ntpEndPoint, ref errorCode);
return errorCode == 0 && sendCount == packet.Bytes.Length;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b2ea9eb0388b74e7787ad18400879fdd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 68178e7c68fcc344990181ce7dee4a3c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: a50bd9a009c8dfc4ebd88cc8101225a7
labels:
- Tween
- Tweening
- Animation
- HOTween
- Paths
- iTween
- DFTween
- LeanTween
- Ease
- Easing
- Shake
- Punch
- 2DToolkit
- TextMeshPro
- Text
folderAsset: yes
DefaultImporter:
userData:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 34192c5e0d14aee43a0e86cc4823268a
TextScriptImporter:
userData:

Binary file not shown.

View File

@@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 4f007001a22b3d24dae350342c4d19c8
DefaultImporter:
userData:

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: a811bde74b26b53498b4f6d872b09b6d
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: b27f58ae5d5c33a4bb2d1f4f34bd036d
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,110 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>DOTweenEditor</name>
</assembly>
<members>
<member name="M:DG.DOTweenEditor.DOTweenEditorPreview.Start(System.Action)">
<summary>
Starts the update loop of tween in the editor. Has no effect during playMode.
</summary>
<param name="onPreviewUpdated">Eventual callback to call after every update</param>
</member>
<member name="M:DG.DOTweenEditor.DOTweenEditorPreview.Stop(System.Boolean,System.Boolean)">
<summary>
Stops the update loop and clears the onPreviewUpdated callback.
</summary>
<param name="resetTweenTargets">If TRUE also resets the tweened objects to their original state.
Note that this works by calling Rewind on all tweens, so it will work correctly
only if you have a single tween type per object and it wasn't killed</param>
<param name="clearTweens">If TRUE also kills any cached tween</param>
</member>
<member name="M:DG.DOTweenEditor.DOTweenEditorPreview.PrepareTweenForPreview(DG.Tweening.Tween,System.Boolean,System.Boolean,System.Boolean)">
<summary>
Readies the tween for editor preview by setting its UpdateType to Manual plus eventual extra settings.
</summary>
<param name="t">The tween to ready</param>
<param name="clearCallbacks">If TRUE (recommended) removes all callbacks (OnComplete/Rewind/etc)</param>
<param name="preventAutoKill">If TRUE prevents the tween from being auto-killed at completion</param>
<param name="andPlay">If TRUE starts playing the tween immediately</param>
</member>
<member name="F:DG.DOTweenEditor.EditorVersion.Version">
<summary>Full major version + first minor version (ex: 2018.1f)</summary>
</member>
<member name="F:DG.DOTweenEditor.EditorVersion.MajorVersion">
<summary>Major version</summary>
</member>
<member name="F:DG.DOTweenEditor.EditorVersion.MinorVersion">
<summary>First minor version (ex: in 2018.1 it would be 1)</summary>
</member>
<member name="M:DG.DOTweenEditor.EditorUtils.SetEditorTexture(UnityEngine.Texture2D,UnityEngine.FilterMode,System.Int32)">
<summary>
Checks that the given editor texture use the correct import settings,
and applies them if they're incorrect.
</summary>
</member>
<member name="M:DG.DOTweenEditor.EditorUtils.DOTweenSetupRequired">
<summary>
Returns TRUE if setup is required
</summary>
</member>
<member name="M:DG.DOTweenEditor.EditorUtils.AssetExists(System.String)">
<summary>
Returns TRUE if the file/directory at the given path exists.
</summary>
<param name="adbPath">Path, relative to Unity's project folder</param>
<returns></returns>
</member>
<member name="M:DG.DOTweenEditor.EditorUtils.ADBPathToFullPath(System.String)">
<summary>
Converts the given project-relative path to a full path,
with backward (\) slashes).
</summary>
</member>
<member name="M:DG.DOTweenEditor.EditorUtils.FullPathToADBPath(System.String)">
<summary>
Converts the given full path to a path usable with AssetDatabase methods
(relative to Unity's project folder, and with the correct Unity forward (/) slashes).
</summary>
</member>
<member name="M:DG.DOTweenEditor.EditorUtils.ConnectToSourceAsset``1(System.String,System.Boolean)">
<summary>
Connects to a <see cref="T:UnityEngine.ScriptableObject"/> asset.
If the asset already exists at the given path, loads it and returns it.
Otherwise, either returns NULL or automatically creates it before loading and returning it
(depending on the given parameters).
</summary>
<typeparam name="T">Asset type</typeparam>
<param name="adbFilePath">File path (relative to Unity's project folder)</param>
<param name="createIfMissing">If TRUE and the requested asset doesn't exist, forces its creation</param>
</member>
<member name="M:DG.DOTweenEditor.EditorUtils.GetAssemblyFilePath(System.Reflection.Assembly)">
<summary>
Full path for the given loaded assembly, assembly file included
</summary>
</member>
<member name="M:DG.DOTweenEditor.EditorUtils.AddGlobalDefine(System.String)">
<summary>
Adds the given global define if it's not already present
</summary>
</member>
<member name="M:DG.DOTweenEditor.EditorUtils.RemoveGlobalDefine(System.String)">
<summary>
Removes the given global define if it's present
</summary>
</member>
<member name="M:DG.DOTweenEditor.EditorUtils.HasGlobalDefine(System.String,System.Nullable{UnityEditor.BuildTargetGroup})">
<summary>
Returns TRUE if the given global define is present in all the <see cref="T:UnityEditor.BuildTargetGroup"/>
or only in the given <see cref="T:UnityEditor.BuildTargetGroup"/>, depending on passed parameters.<para/>
</summary>
<param name="id"></param>
<param name="buildTargetGroup"><see cref="T:UnityEditor.BuildTargetGroup"/>to use. Leave NULL to check in all of them.</param>
</member>
<member name="T:DG.DOTweenEditor.DOTweenDefines">
<summary>
Not used as menu item anymore, but as a utiity function
</summary>
</member>
</members>
</doc>

View File

@@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 2e2c6224d345d9249acfa6e8ef40bb2d
TextScriptImporter:
userData:

View File

@@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 8f46310a8b0a8f04a92993c37c713243
DefaultImporter:
userData:

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 45d5034162d6cf04dbe46da84fc7d074
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 0034ebae0c2a9344e897db1160d71b6d
folderAsset: yes
DefaultImporter:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 8da095e39e9b4df488dfd436f81116d6
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 128
textureSettings:
filterMode: 1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

View File

@@ -0,0 +1,68 @@
fileFormatVersion: 2
guid: 61521df2e071645488ba3d05e49289ae
timeCreated: 1602317874
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 7051dba417b3d53409f2918f1ea4938d
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 256
textureSettings:
filterMode: 1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 519694efe2bb2914788b151fbd8c01f4
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 1
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 0
textureType: -1
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 78a59ca99f8987941adb61f9e14a06a7
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 512
textureSettings:
filterMode: 1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

View File

@@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 143604b8bad857d47a6f7cc7a533e2dc
folderAsset: yes
DefaultImporter:
userData:

View File

@@ -0,0 +1,202 @@
// Author: Daniele Giardini - http://www.demigiant.com
// Created: 2018/07/13
#if true // MODULE_MARKER
using System;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using UnityEngine;
#if UNITY_5 || UNITY_2017_1_OR_NEWER
using UnityEngine.Audio; // Required for AudioMixer
#endif
#pragma warning disable 1591
namespace DG.Tweening
{
public static class DOTweenModuleAudio
{
#region Shortcuts
#region Audio
/// <summary>Tweens an AudioSource's volume to the given value.
/// Also stores the AudioSource as the tween's target so it can be used for filtered operations</summary>
/// <param name="endValue">The end value to reach (0 to 1)</param><param name="duration">The duration of the tween</param>
public static TweenerCore<float, float, FloatOptions> DOFade(this AudioSource target, float endValue, float duration)
{
if (endValue < 0) endValue = 0;
else if (endValue > 1) endValue = 1;
TweenerCore<float, float, FloatOptions> t = DOTween.To(() => target.volume, x => target.volume = x, endValue, duration);
t.SetTarget(target);
return t;
}
/// <summary>Tweens an AudioSource's pitch to the given value.
/// Also stores the AudioSource as the tween's target so it can be used for filtered operations</summary>
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
public static TweenerCore<float, float, FloatOptions> DOPitch(this AudioSource target, float endValue, float duration)
{
TweenerCore<float, float, FloatOptions> t = DOTween.To(() => target.pitch, x => target.pitch = x, endValue, duration);
t.SetTarget(target);
return t;
}
#endregion
#if UNITY_5 || UNITY_2017_1_OR_NEWER
#region AudioMixer (Unity 5 or Newer)
/// <summary>Tweens an AudioMixer's exposed float to the given value.
/// Also stores the AudioMixer as the tween's target so it can be used for filtered operations.
/// Note that you need to manually expose a float in an AudioMixerGroup in order to be able to tween it from an AudioMixer.</summary>
/// <param name="floatName">Name given to the exposed float to set</param>
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
public static TweenerCore<float, float, FloatOptions> DOSetFloat(this AudioMixer target, string floatName, float endValue, float duration)
{
TweenerCore<float, float, FloatOptions> t = DOTween.To(()=> {
float currVal;
target.GetFloat(floatName, out currVal);
return currVal;
}, x=> target.SetFloat(floatName, x), endValue, duration);
t.SetTarget(target);
return t;
}
#region Operation Shortcuts
/// <summary>
/// Completes all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens completed
/// (meaning the tweens that don't have infinite loops and were not already complete)
/// </summary>
/// <param name="withCallbacks">For Sequences only: if TRUE also internal Sequence callbacks will be fired,
/// otherwise they will be ignored</param>
public static int DOComplete(this AudioMixer target, bool withCallbacks = false)
{
return DOTween.Complete(target, withCallbacks);
}
/// <summary>
/// Kills all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens killed.
/// </summary>
/// <param name="complete">If TRUE completes the tween before killing it</param>
public static int DOKill(this AudioMixer target, bool complete = false)
{
return DOTween.Kill(target, complete);
}
/// <summary>
/// Flips the direction (backwards if it was going forward or viceversa) of all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens flipped.
/// </summary>
public static int DOFlip(this AudioMixer target)
{
return DOTween.Flip(target);
}
/// <summary>
/// Sends to the given position all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens involved.
/// </summary>
/// <param name="to">Time position to reach
/// (if higher than the whole tween duration the tween will simply reach its end)</param>
/// <param name="andPlay">If TRUE will play the tween after reaching the given position, otherwise it will pause it</param>
public static int DOGoto(this AudioMixer target, float to, bool andPlay = false)
{
return DOTween.Goto(target, to, andPlay);
}
/// <summary>
/// Pauses all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens paused.
/// </summary>
public static int DOPause(this AudioMixer target)
{
return DOTween.Pause(target);
}
/// <summary>
/// Plays all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens played.
/// </summary>
public static int DOPlay(this AudioMixer target)
{
return DOTween.Play(target);
}
/// <summary>
/// Plays backwards all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens played.
/// </summary>
public static int DOPlayBackwards(this AudioMixer target)
{
return DOTween.PlayBackwards(target);
}
/// <summary>
/// Plays forward all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens played.
/// </summary>
public static int DOPlayForward(this AudioMixer target)
{
return DOTween.PlayForward(target);
}
/// <summary>
/// Restarts all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens restarted.
/// </summary>
public static int DORestart(this AudioMixer target)
{
return DOTween.Restart(target);
}
/// <summary>
/// Rewinds all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens rewinded.
/// </summary>
public static int DORewind(this AudioMixer target)
{
return DOTween.Rewind(target);
}
/// <summary>
/// Smoothly rewinds all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens rewinded.
/// </summary>
public static int DOSmoothRewind(this AudioMixer target)
{
return DOTween.SmoothRewind(target);
}
/// <summary>
/// Toggles the paused state (plays if it was paused, pauses if it was playing) of all tweens that have this target as a reference
/// (meaning tweens that were started from this target, or that had this target added as an Id)
/// and returns the total number of tweens involved.
/// </summary>
public static int DOTogglePause(this AudioMixer target)
{
return DOTween.TogglePause(target);
}
#endregion
#endregion
#endif
#endregion
}
}
#endif

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b766d08851589514b97afb23c6f30a70
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,142 @@
using UnityEngine;
#if false || EPO_DOTWEEN // MODULE_MARKER
using EPOOutline;
using DG.Tweening.Plugins.Options;
using DG.Tweening;
using DG.Tweening.Core;
namespace DG.Tweening
{
public static class DOTweenModuleEPOOutline
{
public static int DOKill(this SerializedPass target, bool complete)
{
return DOTween.Kill(target, complete);
}
public static TweenerCore<float, float, FloatOptions> DOFloat(this SerializedPass target, string propertyName, float endValue, float duration)
{
var tweener = DOTween.To(() => target.GetFloat(propertyName), x => target.SetFloat(propertyName, x), endValue, duration);
tweener.SetOptions(true).SetTarget(target);
return tweener;
}
public static TweenerCore<Color, Color, ColorOptions> DOFade(this SerializedPass target, string propertyName, float endValue, float duration)
{
var tweener = DOTween.ToAlpha(() => target.GetColor(propertyName), x => target.SetColor(propertyName, x), endValue, duration);
tweener.SetOptions(true).SetTarget(target);
return tweener;
}
public static TweenerCore<Color, Color, ColorOptions> DOColor(this SerializedPass target, string propertyName, Color endValue, float duration)
{
var tweener = DOTween.To(() => target.GetColor(propertyName), x => target.SetColor(propertyName, x), endValue, duration);
tweener.SetOptions(false).SetTarget(target);
return tweener;
}
public static TweenerCore<Vector4, Vector4, VectorOptions> DOVector(this SerializedPass target, string propertyName, Vector4 endValue, float duration)
{
var tweener = DOTween.To(() => target.GetVector(propertyName), x => target.SetVector(propertyName, x), endValue, duration);
tweener.SetOptions(false).SetTarget(target);
return tweener;
}
public static TweenerCore<float, float, FloatOptions> DOFloat(this SerializedPass target, int propertyId, float endValue, float duration)
{
var tweener = DOTween.To(() => target.GetFloat(propertyId), x => target.SetFloat(propertyId, x), endValue, duration);
tweener.SetOptions(true).SetTarget(target);
return tweener;
}
public static TweenerCore<Color, Color, ColorOptions> DOFade(this SerializedPass target, int propertyId, float endValue, float duration)
{
var tweener = DOTween.ToAlpha(() => target.GetColor(propertyId), x => target.SetColor(propertyId, x), endValue, duration);
tweener.SetOptions(true).SetTarget(target);
return tweener;
}
public static TweenerCore<Color, Color, ColorOptions> DOColor(this SerializedPass target, int propertyId, Color endValue, float duration)
{
var tweener = DOTween.To(() => target.GetColor(propertyId), x => target.SetColor(propertyId, x), endValue, duration);
tweener.SetOptions(false).SetTarget(target);
return tweener;
}
public static TweenerCore<Vector4, Vector4, VectorOptions> DOVector(this SerializedPass target, int propertyId, Vector4 endValue, float duration)
{
var tweener = DOTween.To(() => target.GetVector(propertyId), x => target.SetVector(propertyId, x), endValue, duration);
tweener.SetOptions(false).SetTarget(target);
return tweener;
}
public static int DOKill(this Outlinable.OutlineProperties target, bool complete = false)
{
return DOTween.Kill(target, complete);
}
public static int DOKill(this Outliner target, bool complete = false)
{
return DOTween.Kill(target, complete);
}
public static TweenerCore<Color, Color, ColorOptions> DOFade(this Outlinable.OutlineProperties target, float endValue, float duration)
{
var tweener = DOTween.ToAlpha(() => target.Color, x => target.Color = x, endValue, duration);
tweener.SetOptions(true).SetTarget(target);
return tweener;
}
public static TweenerCore<Color, Color, ColorOptions> DOColor(this Outlinable.OutlineProperties target, Color endValue, float duration)
{
var tweener = DOTween.To(() => target.Color, x => target.Color = x, endValue, duration);
tweener.SetOptions(false).SetTarget(target);
return tweener;
}
public static TweenerCore<float, float, FloatOptions> DODilateShift(this Outlinable.OutlineProperties target, float endValue, float duration, bool snapping = false)
{
var tweener = DOTween.To(() => target.DilateShift, x => target.DilateShift = x, endValue, duration);
tweener.SetOptions(snapping).SetTarget(target);
return tweener;
}
public static TweenerCore<float, float, FloatOptions> DOBlurShift(this Outlinable.OutlineProperties target, float endValue, float duration, bool snapping = false)
{
var tweener = DOTween.To(() => target.BlurShift, x => target.BlurShift = x, endValue, duration);
tweener.SetOptions(snapping).SetTarget(target);
return tweener;
}
public static TweenerCore<float, float, FloatOptions> DOBlurShift(this Outliner target, float endValue, float duration, bool snapping = false)
{
var tweener = DOTween.To(() => target.BlurShift, x => target.BlurShift = x, endValue, duration);
tweener.SetOptions(snapping).SetTarget(target);
return tweener;
}
public static TweenerCore<float, float, FloatOptions> DODilateShift(this Outliner target, float endValue, float duration, bool snapping = false)
{
var tweener = DOTween.To(() => target.DilateShift, x => target.DilateShift = x, endValue, duration);
tweener.SetOptions(snapping).SetTarget(target);
return tweener;
}
public static TweenerCore<float, float, FloatOptions> DOInfoRendererScale(this Outliner target, float endValue, float duration, bool snapping = false)
{
var tweener = DOTween.To(() => target.InfoRendererScale, x => target.InfoRendererScale = x, endValue, duration);
tweener.SetOptions(snapping).SetTarget(target);
return tweener;
}
public static TweenerCore<float, float, FloatOptions> DOPrimaryRendererScale(this Outliner target, float endValue, float duration, bool snapping = false)
{
var tweener = DOTween.To(() => target.PrimaryRendererScale, x => target.PrimaryRendererScale = x, endValue, duration);
tweener.SetOptions(snapping).SetTarget(target);
return tweener;
}
}
}
#endif

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e944529dcaee98f4e9498d80e541d93e
timeCreated: 1602593330
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,216 @@
// Author: Daniele Giardini - http://www.demigiant.com
// Created: 2018/07/13
#if true // MODULE_MARKER
using System;
using DG.Tweening.Core;
using DG.Tweening.Core.Enums;
using DG.Tweening.Plugins;
using DG.Tweening.Plugins.Core.PathCore;
using DG.Tweening.Plugins.Options;
using UnityEngine;
#pragma warning disable 1591
namespace DG.Tweening
{
public static class DOTweenModulePhysics
{
#region Shortcuts
#region Rigidbody
/// <summary>Tweens a Rigidbody's position to the given value.
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMove(this Rigidbody target, Vector3 endValue, float duration, bool snapping = false)
{
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, endValue, duration);
t.SetOptions(snapping).SetTarget(target);
return t;
}
/// <summary>Tweens a Rigidbody's X position to the given value.
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMoveX(this Rigidbody target, float endValue, float duration, bool snapping = false)
{
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, new Vector3(endValue, 0, 0), duration);
t.SetOptions(AxisConstraint.X, snapping).SetTarget(target);
return t;
}
/// <summary>Tweens a Rigidbody's Y position to the given value.
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMoveY(this Rigidbody target, float endValue, float duration, bool snapping = false)
{
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, new Vector3(0, endValue, 0), duration);
t.SetOptions(AxisConstraint.Y, snapping).SetTarget(target);
return t;
}
/// <summary>Tweens a Rigidbody's Z position to the given value.
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMoveZ(this Rigidbody target, float endValue, float duration, bool snapping = false)
{
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, new Vector3(0, 0, endValue), duration);
t.SetOptions(AxisConstraint.Z, snapping).SetTarget(target);
return t;
}
/// <summary>Tweens a Rigidbody's rotation to the given value.
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
/// <param name="mode">Rotation mode</param>
public static TweenerCore<Quaternion, Vector3, QuaternionOptions> DORotate(this Rigidbody target, Vector3 endValue, float duration, RotateMode mode = RotateMode.Fast)
{
TweenerCore<Quaternion, Vector3, QuaternionOptions> t = DOTween.To(() => target.rotation, target.MoveRotation, endValue, duration);
t.SetTarget(target);
t.plugOptions.rotateMode = mode;
return t;
}
/// <summary>Tweens a Rigidbody's rotation so that it will look towards the given position.
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
/// <param name="towards">The position to look at</param><param name="duration">The duration of the tween</param>
/// <param name="axisConstraint">Eventual axis constraint for the rotation</param>
/// <param name="up">The vector that defines in which direction up is (default: Vector3.up)</param>
public static TweenerCore<Quaternion, Vector3, QuaternionOptions> DOLookAt(this Rigidbody target, Vector3 towards, float duration, AxisConstraint axisConstraint = AxisConstraint.None, Vector3? up = null)
{
TweenerCore<Quaternion, Vector3, QuaternionOptions> t = DOTween.To(() => target.rotation, target.MoveRotation, towards, duration)
.SetTarget(target).SetSpecialStartupMode(SpecialStartupMode.SetLookAt);
t.plugOptions.axisConstraint = axisConstraint;
t.plugOptions.up = (up == null) ? Vector3.up : (Vector3)up;
return t;
}
#region Special
/// <summary>Tweens a Rigidbody's position to the given value, while also applying a jump effect along the Y axis.
/// Returns a Sequence instead of a Tweener.
/// Also stores the Rigidbody as the tween's target so it can be used for filtered operations</summary>
/// <param name="endValue">The end value to reach</param>
/// <param name="jumpPower">Power of the jump (the max height of the jump is represented by this plus the final Y offset)</param>
/// <param name="numJumps">Total number of jumps</param>
/// <param name="duration">The duration of the tween</param>
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
public static Sequence DOJump(this Rigidbody target, Vector3 endValue, float jumpPower, int numJumps, float duration, bool snapping = false)
{
if (numJumps < 1) numJumps = 1;
float startPosY = 0;
float offsetY = -1;
bool offsetYSet = false;
Sequence s = DOTween.Sequence();
Tween yTween = DOTween.To(() => target.position, target.MovePosition, new Vector3(0, jumpPower, 0), duration / (numJumps * 2))
.SetOptions(AxisConstraint.Y, snapping).SetEase(Ease.OutQuad).SetRelative()
.SetLoops(numJumps * 2, LoopType.Yoyo)
.OnStart(() => startPosY = target.position.y);
s.Append(DOTween.To(() => target.position, target.MovePosition, new Vector3(endValue.x, 0, 0), duration)
.SetOptions(AxisConstraint.X, snapping).SetEase(Ease.Linear)
).Join(DOTween.To(() => target.position, target.MovePosition, new Vector3(0, 0, endValue.z), duration)
.SetOptions(AxisConstraint.Z, snapping).SetEase(Ease.Linear)
).Join(yTween)
.SetTarget(target).SetEase(DOTween.defaultEaseType);
yTween.OnUpdate(() => {
if (!offsetYSet) {
offsetYSet = true;
offsetY = s.isRelative ? endValue.y : endValue.y - startPosY;
}
Vector3 pos = target.position;
pos.y += DOVirtual.EasedValue(0, offsetY, yTween.ElapsedPercentage(), Ease.OutQuad);
target.MovePosition(pos);
});
return s;
}
/// <summary>Tweens a Rigidbody's position through the given path waypoints, using the chosen path algorithm.
/// Also stores the Rigidbody as the tween's target so it can be used for filtered operations.
/// <para>NOTE: to tween a rigidbody correctly it should be set to kinematic at least while being tweened.</para>
/// <para>BEWARE: doesn't work on Windows Phone store (waiting for Unity to fix their own bug).
/// If you plan to publish there you should use a regular transform.DOPath.</para></summary>
/// <param name="path">The waypoints to go through</param>
/// <param name="duration">The duration of the tween</param>
/// <param name="pathType">The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points)</param>
/// <param name="pathMode">The path mode: 3D, side-scroller 2D, top-down 2D</param>
/// <param name="resolution">The resolution of the path (useless in case of Linear paths): higher resolutions make for more detailed curved paths but are more expensive.
/// Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints</param>
/// <param name="gizmoColor">The color of the path (shown when gizmos are active in the Play panel and the tween is running)</param>
public static TweenerCore<Vector3, Path, PathOptions> DOPath(
this Rigidbody target, Vector3[] path, float duration, PathType pathType = PathType.Linear,
PathMode pathMode = PathMode.Full3D, int resolution = 10, Color? gizmoColor = null
)
{
if (resolution < 1) resolution = 1;
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => target.position, target.MovePosition, new Path(pathType, path, resolution, gizmoColor), duration)
.SetTarget(target).SetUpdate(UpdateType.Fixed);
t.plugOptions.isRigidbody = true;
t.plugOptions.mode = pathMode;
return t;
}
/// <summary>Tweens a Rigidbody's localPosition through the given path waypoints, using the chosen path algorithm.
/// Also stores the Rigidbody as the tween's target so it can be used for filtered operations
/// <para>NOTE: to tween a rigidbody correctly it should be set to kinematic at least while being tweened.</para>
/// <para>BEWARE: doesn't work on Windows Phone store (waiting for Unity to fix their own bug).
/// If you plan to publish there you should use a regular transform.DOLocalPath.</para></summary>
/// <param name="path">The waypoint to go through</param>
/// <param name="duration">The duration of the tween</param>
/// <param name="pathType">The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points)</param>
/// <param name="pathMode">The path mode: 3D, side-scroller 2D, top-down 2D</param>
/// <param name="resolution">The resolution of the path: higher resolutions make for more detailed curved paths but are more expensive.
/// Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints</param>
/// <param name="gizmoColor">The color of the path (shown when gizmos are active in the Play panel and the tween is running)</param>
public static TweenerCore<Vector3, Path, PathOptions> DOLocalPath(
this Rigidbody target, Vector3[] path, float duration, PathType pathType = PathType.Linear,
PathMode pathMode = PathMode.Full3D, int resolution = 10, Color? gizmoColor = null
)
{
if (resolution < 1) resolution = 1;
Transform trans = target.transform;
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => trans.localPosition, x => target.MovePosition(trans.parent == null ? x : trans.parent.TransformPoint(x)), new Path(pathType, path, resolution, gizmoColor), duration)
.SetTarget(target).SetUpdate(UpdateType.Fixed);
t.plugOptions.isRigidbody = true;
t.plugOptions.mode = pathMode;
t.plugOptions.useLocalPosition = true;
return t;
}
// Used by path editor when creating the actual tween, so it can pass a pre-compiled path
internal static TweenerCore<Vector3, Path, PathOptions> DOPath(
this Rigidbody target, Path path, float duration, PathMode pathMode = PathMode.Full3D
)
{
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => target.position, target.MovePosition, path, duration)
.SetTarget(target);
t.plugOptions.isRigidbody = true;
t.plugOptions.mode = pathMode;
return t;
}
internal static TweenerCore<Vector3, Path, PathOptions> DOLocalPath(
this Rigidbody target, Path path, float duration, PathMode pathMode = PathMode.Full3D
)
{
Transform trans = target.transform;
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => trans.localPosition, x => target.MovePosition(trans.parent == null ? x : trans.parent.TransformPoint(x)), path, duration)
.SetTarget(target);
t.plugOptions.isRigidbody = true;
t.plugOptions.mode = pathMode;
t.plugOptions.useLocalPosition = true;
return t;
}
#endregion
#endregion
#endregion
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More