mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-11-11 08:38:45 +00:00
提交Unity 联机Pro
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
#if !BESTHTTP_DISABLE_SOCKETIO
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BestHTTP.SocketIO.Events
|
||||
{
|
||||
public delegate void SocketIOCallback(Socket socket, Packet packet, params object[] args);
|
||||
public delegate void SocketIOAckCallback(Socket socket, Packet packet, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// A class to describe an event, and its metadatas.
|
||||
/// </summary>
|
||||
internal sealed class EventDescriptor
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// List of callback delegates.
|
||||
/// </summary>
|
||||
public List<SocketIOCallback> Callbacks { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If this property is true, callbacks are removed automatically after the event dispatch.
|
||||
/// </summary>
|
||||
public bool OnlyOnce { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If this property is true, the dispatching packet's Payload will be decoded using the Manager's Encoder.
|
||||
/// </summary>
|
||||
public bool AutoDecodePayload { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Cache an array on a hot-path.
|
||||
/// </summary>
|
||||
private SocketIOCallback[] CallbackArray;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor to create an EventDescriptor instance and set the meta-datas.
|
||||
/// </summary>
|
||||
public EventDescriptor(bool onlyOnce, bool autoDecodePayload, SocketIOCallback callback)
|
||||
{
|
||||
this.OnlyOnce = onlyOnce;
|
||||
this.AutoDecodePayload = autoDecodePayload;
|
||||
this.Callbacks = new List<SocketIOCallback>(1);
|
||||
|
||||
if (callback != null)
|
||||
Callbacks.Add(callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will call the callback delegates with the given parameters and remove the callbacks if this descriptor marked with a true OnlyOnce property.
|
||||
/// </summary>
|
||||
public void Call(Socket socket, Packet packet, params object[] args)
|
||||
{
|
||||
int callbackCount = Callbacks.Count;
|
||||
if (CallbackArray == null || CallbackArray.Length < callbackCount)
|
||||
Array.Resize(ref CallbackArray, callbackCount);
|
||||
|
||||
// Copy the callback delegates to an array, because in one of the callbacks we can modify the list(by calling On/Once/Off in an event handler)
|
||||
// This way we can prevent some strange bug
|
||||
Callbacks.CopyTo(CallbackArray);
|
||||
|
||||
// Go through the delegates and call them
|
||||
for (int i = 0; i < callbackCount; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Call the delegate.
|
||||
SocketIOCallback callback = CallbackArray[i];
|
||||
if (callback!= null)
|
||||
callback(socket, packet, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Do not try to emit a new Error when we already tried to deliver an Error, possible causing a
|
||||
// stack overflow
|
||||
if (args == null || args.Length == 0 || !(args[0] is Error))
|
||||
(socket as ISocket).EmitError(SocketIOErrors.User, ex.Message + " " + ex.StackTrace);
|
||||
|
||||
HTTPManager.Logger.Exception("EventDescriptor", "Call", ex);
|
||||
}
|
||||
|
||||
// If these callbacks has to be called only once, remove them from the main list
|
||||
if (this.OnlyOnce)
|
||||
Callbacks.Remove(CallbackArray[i]);
|
||||
|
||||
// Don't keep any reference avoiding memory leaks
|
||||
CallbackArray[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab942858f5ff2a4458ec312bc2955779
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
#if !BESTHTTP_DISABLE_SOCKETIO
|
||||
|
||||
using System;
|
||||
|
||||
namespace BestHTTP.SocketIO.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class to provide functions to an easy Enum->string conversation of the transport and SocketIO evenet types.
|
||||
/// </summary>
|
||||
public static class EventNames
|
||||
{
|
||||
public const string Connect = "connect";
|
||||
public const string Disconnect = "disconnect";
|
||||
public const string Event = "event";
|
||||
public const string Ack = "ack";
|
||||
public const string Error = "error";
|
||||
public const string BinaryEvent = "binaryevent";
|
||||
public const string BinaryAck = "binaryack";
|
||||
|
||||
private static string[] SocketIONames = new string[] { "unknown", "connect", "disconnect", "event", "ack", "error", "binaryevent", "binaryack" };
|
||||
private static string[] TransportNames = new string[] { "unknown", "open", "close", "ping", "pong", "message", "upgrade", "noop" };
|
||||
private static string[] BlacklistedEvents = new string[] { "connect", "connect_error", "connect_timeout", "disconnect", "error", "reconnect",
|
||||
"reconnect_attempt", "reconnect_failed", "reconnect_error", "reconnecting" };
|
||||
|
||||
public static string GetNameFor(SocketIOEventTypes type)
|
||||
{
|
||||
return SocketIONames[(int)type + 1];
|
||||
}
|
||||
|
||||
public static string GetNameFor(TransportEventTypes transEvent)
|
||||
{
|
||||
return TransportNames[(int)transEvent + 1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks an event name whether it's blacklisted or not.
|
||||
/// </summary>
|
||||
public static bool IsBlacklisted(string eventName)
|
||||
{
|
||||
for (int i = 0; i < BlacklistedEvents.Length; ++i)
|
||||
if (string.Compare(BlacklistedEvents[i], eventName, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ab78cfee54d71543bec1cdef098cd4b
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,161 @@
|
||||
#if !BESTHTTP_DISABLE_SOCKETIO
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BestHTTP.SocketIO.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// This class helps keep track and maintain EventDescriptor instances and dispatching packets to the right delegates.
|
||||
/// </summary>
|
||||
internal sealed class EventTable
|
||||
{
|
||||
#region Privates
|
||||
|
||||
/// <summary>
|
||||
/// The Socket that this EventTable is bound to.
|
||||
/// </summary>
|
||||
private Socket Socket { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The 'EventName -> List of events' mapping.
|
||||
/// </summary>
|
||||
private Dictionary<string, List<EventDescriptor>> Table = new Dictionary<string, List<EventDescriptor>>();
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Constructor to create an instance and bind it to a socket.
|
||||
/// </summary>
|
||||
public EventTable(Socket socket)
|
||||
{
|
||||
this.Socket = socket;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a callback to a name with the given metadata.
|
||||
/// </summary>
|
||||
public void Register(string eventName, SocketIOCallback callback, bool onlyOnce, bool autoDecodePayload)
|
||||
{
|
||||
List<EventDescriptor> events;
|
||||
if (!Table.TryGetValue(eventName, out events))
|
||||
Table.Add(eventName, events = new List<EventDescriptor>(1));
|
||||
|
||||
// Find a matching descriptor
|
||||
var desc = events.Find((d) => d.OnlyOnce == onlyOnce && d.AutoDecodePayload == autoDecodePayload);
|
||||
|
||||
// If not found, create one
|
||||
if (desc == null)
|
||||
events.Add(new EventDescriptor(onlyOnce, autoDecodePayload, callback));
|
||||
else // if found, add the new callback
|
||||
desc.Callbacks.Add(callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all events that registered for the given name.
|
||||
/// </summary>
|
||||
public void Unregister(string eventName)
|
||||
{
|
||||
Table.Remove(eventName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Unregister(string eventName, SocketIOCallback callback)
|
||||
{
|
||||
List<EventDescriptor> events;
|
||||
if (Table.TryGetValue(eventName, out events))
|
||||
for (int i = 0; i < events.Count; ++i)
|
||||
events[i].Callbacks.Remove(callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will call the delegates that associated to the given eventName.
|
||||
/// </summary>
|
||||
public void Call(string eventName, Packet packet, params object[] args)
|
||||
{
|
||||
List<EventDescriptor> events;
|
||||
|
||||
if (Table.TryGetValue(eventName, out events))
|
||||
{
|
||||
if (HTTPManager.Logger.Level <= BestHTTP.Logger.Loglevels.All)
|
||||
HTTPManager.Logger.Verbose("EventTable", string.Format("Call - {0} ({1})", eventName, events.Count));
|
||||
|
||||
for (int i = 0; i < events.Count; ++i)
|
||||
events[i].Call(Socket, packet, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HTTPManager.Logger.Level <= BestHTTP.Logger.Loglevels.All)
|
||||
HTTPManager.Logger.Verbose("EventTable", string.Format("Call - {0} (0)", eventName));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function will get the eventName from the packet's Payload, and optionally will decode it from Json.
|
||||
/// </summary>
|
||||
public void Call(Packet packet)
|
||||
{
|
||||
string eventName = packet.DecodeEventName();
|
||||
string typeName = packet.SocketIOEvent != SocketIOEventTypes.Unknown ? EventNames.GetNameFor(packet.SocketIOEvent) : EventNames.GetNameFor(packet.TransportEvent);
|
||||
object[] args = null;
|
||||
|
||||
if (!HasSubsciber(eventName) && !HasSubsciber(typeName))
|
||||
return;
|
||||
|
||||
// If this is an Event or BinaryEvent message, or we have a subscriber with AutoDecodePayload, then
|
||||
// we have to decode the packet's Payload.
|
||||
if (packet.TransportEvent == TransportEventTypes.Message && (packet.SocketIOEvent == SocketIOEventTypes.Event || packet.SocketIOEvent == SocketIOEventTypes.BinaryEvent) && ShouldDecodePayload(eventName))
|
||||
args = packet.Decode(Socket.Manager.Encoder);
|
||||
|
||||
// call event callbacks registered for 'eventName'
|
||||
if (!string.IsNullOrEmpty(eventName))
|
||||
Call(eventName, packet, args);
|
||||
|
||||
if (!packet.IsDecoded && ShouldDecodePayload(typeName))
|
||||
args = packet.Decode(Socket.Manager.Encoder);
|
||||
|
||||
// call event callbacks registered for 'typeName'
|
||||
if (!string.IsNullOrEmpty(typeName))
|
||||
Call(typeName, packet, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all event -> delegate association.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
Table.Clear();
|
||||
}
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Returns true, if for the given event name there are at least one event that needs a decoded
|
||||
/// </summary>
|
||||
/// <param name="eventName"></param>
|
||||
/// <returns></returns>
|
||||
private bool ShouldDecodePayload(string eventName)
|
||||
{
|
||||
List<EventDescriptor> events;
|
||||
|
||||
// If we find at least one EventDescriptor with AutoDecodePayload == true, we have to
|
||||
// decode the whole payload
|
||||
if (Table.TryGetValue(eventName, out events))
|
||||
for (int i = 0; i < events.Count; ++i)
|
||||
if (events[i].AutoDecodePayload && events[i].Callbacks.Count > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool HasSubsciber(string eventName)
|
||||
{
|
||||
return Table.ContainsKey(eventName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62b1e6227e8b13446b06cf83b7ab23e2
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user