From 2f3ffa555890fea299e1725ecc81e7473aedc08b Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Wed, 13 May 2026 13:28:41 +0200 Subject: [PATCH] Initial commit. --- .gitattributes | 4 + ENet.cs | 1197 ++++++++++++++++++++++++++++++++++++++ ENet.cs.meta | 2 + Shazbot.ENet.asmdef | 14 + Shazbot.ENet.asmdef.meta | 7 + enet.dll | 3 + enet.dll.meta | 2 + libenet.so | 3 + libenet.so.meta | 50 ++ package.json | 17 + package.json.meta | 7 + 11 files changed, 1306 insertions(+) create mode 100644 .gitattributes create mode 100644 ENet.cs create mode 100644 ENet.cs.meta create mode 100644 Shazbot.ENet.asmdef create mode 100644 Shazbot.ENet.asmdef.meta create mode 100644 enet.dll create mode 100644 enet.dll.meta create mode 100644 libenet.so create mode 100644 libenet.so.meta create mode 100644 package.json create mode 100644 package.json.meta diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..aecd65e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# Dlls are not pulled unless this comment is here. +*.dll filter=lfs diff=lfs merge=lfs -text +*.so filter=lfs diff=lfs merge=lfs -text +*.dylib filter=lfs diff=lfs merge=lfs -text \ No newline at end of file diff --git a/ENet.cs b/ENet.cs new file mode 100644 index 0000000..2098ad2 --- /dev/null +++ b/ENet.cs @@ -0,0 +1,1197 @@ +/* + * Managed C# wrapper for an extended version of ENet + * Copyright (c) 2013 James Bellinger + * Copyright (c) 2016 Nate Shoffner + * Copyright (c) 2018 Stanislav Denisov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +using System; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +namespace ENet { + [Flags] + public enum PacketFlags { + None = 0, + Reliable = 1 << 0, + Unsequenced = 1 << 1, + NoAllocate = 1 << 2, + UnreliableFragmented = 1 << 3, + Instant = 1 << 4, + Unthrottled = 1 << 5, + Sent = 1 << 8 + } + + public enum EventType { + None = 0, + Connect = 1, + Disconnect = 2, + Data = 3, + Timeout = 4 + } + + public enum PeerState { + Uninitialized = -1, + Disconnected = 0, + Connecting = 1, + AcknowledgingConnect = 2, + ConnectionPending = 3, + ConnectionSucceeded = 4, + Connected = 5, + DisconnectLater = 6, + Disconnecting = 7, + AcknowledgingDisconnect = 8, + Zombie = 9 + } + + [StructLayout(LayoutKind.Explicit, Size = 18)] + internal struct ENetAddress { + [FieldOffset(16)] + public ushort port; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct ENetEvent { + public EventType type; + public IntPtr peer; + public byte channelID; + public uint data; + public IntPtr packet; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct ENetCallbacks { + public AllocCallback malloc; + public FreeCallback free; + public NoMemoryCallback noMemory; + } + + public delegate IntPtr AllocCallback(IntPtr size); + public delegate void FreeCallback(IntPtr memory); + public delegate void NoMemoryCallback(); + public delegate void PacketFreeCallback(Packet packet); + public delegate int InterceptCallback(ref Event @event, ref Address address, IntPtr receivedData, int receivedDataLength); + public delegate ulong ChecksumCallback(IntPtr buffers, int bufferCount); + + internal static class ArrayPool { + [ThreadStatic] + private static byte[] byteBuffer; + [ThreadStatic] + private static IntPtr[] pointerBuffer; + + public static byte[] GetByteBuffer() { + if (byteBuffer == null) + byteBuffer = new byte[64]; + + return byteBuffer; + } + + public static IntPtr[] GetPointerBuffer() { + if (pointerBuffer == null) + pointerBuffer = new IntPtr[Library.maxPeers]; + + return pointerBuffer; + } + } + + public struct Address { + private ENetAddress nativeAddress; + + internal ENetAddress NativeData { + get { + return nativeAddress; + } + + set { + nativeAddress = value; + } + } + + internal Address(ENetAddress address) { + nativeAddress = address; + } + + public ushort Port { + get { + return nativeAddress.port; + } + + set { + nativeAddress.port = value; + } + } + + public string GetIP() { + StringBuilder ip = new StringBuilder(1025); + + if (Native.enet_address_get_ip(ref nativeAddress, ip, (IntPtr)ip.Capacity) != 0) + return String.Empty; + + return ip.ToString(); + } + + public bool SetIP(string ip) { + if (ip == null) + throw new ArgumentNullException("ip"); + + return Native.enet_address_set_ip(ref nativeAddress, ip) == 0; + } + + public string GetHost() { + StringBuilder hostName = new StringBuilder(1025); + + if (Native.enet_address_get_hostname(ref nativeAddress, hostName, (IntPtr)hostName.Capacity) != 0) + return String.Empty; + + return hostName.ToString(); + } + + public bool SetHost(string hostName) { + if (hostName == null) + throw new ArgumentNullException("hostName"); + + return Native.enet_address_set_hostname(ref nativeAddress, hostName) == 0; + } + } + + public struct Event { + private ENetEvent nativeEvent; + + internal ENetEvent NativeData { + get { + return nativeEvent; + } + + set { + nativeEvent = value; + } + } + + internal Event(ENetEvent @event) { + nativeEvent = @event; + } + + public EventType Type { + get { + return nativeEvent.type; + } + } + + public Peer Peer { + get { + return new Peer(nativeEvent.peer); + } + } + + public byte ChannelID { + get { + return nativeEvent.channelID; + } + } + + public uint Data { + get { + return nativeEvent.data; + } + } + + public Packet Packet { + get { + return new Packet(nativeEvent.packet); + } + } + } + + public class Callbacks { + private ENetCallbacks nativeCallbacks; + + internal ENetCallbacks NativeData { + get { + return nativeCallbacks; + } + + set { + nativeCallbacks = value; + } + } + + public Callbacks(AllocCallback allocCallback, FreeCallback freeCallback, NoMemoryCallback noMemoryCallback) { + nativeCallbacks.malloc = allocCallback; + nativeCallbacks.free = freeCallback; + nativeCallbacks.noMemory = noMemoryCallback; + } + } + + public struct Packet : IDisposable { + private IntPtr nativePacket; + + internal IntPtr NativeData { + get { + return nativePacket; + } + + set { + nativePacket = value; + } + } + + internal Packet(IntPtr packet) { + nativePacket = packet; + } + + public void Dispose() { + if (nativePacket != IntPtr.Zero) { + Native.enet_packet_dispose(nativePacket); + nativePacket = IntPtr.Zero; + } + } + + public bool IsSet { + get { + return nativePacket != IntPtr.Zero; + } + } + + public IntPtr Data { + get { + ThrowIfNotCreated(); + + return Native.enet_packet_get_data(nativePacket); + } + } + + public IntPtr UserData { + get { + ThrowIfNotCreated(); + + return Native.enet_packet_get_user_data(nativePacket); + } + + set { + ThrowIfNotCreated(); + + Native.enet_packet_set_user_data(nativePacket, value); + } + } + + public int Length { + get { + ThrowIfNotCreated(); + + return Native.enet_packet_get_length(nativePacket); + } + } + + public bool HasReferences { + get { + ThrowIfNotCreated(); + + return Native.enet_packet_check_references(nativePacket) != 0; + } + } + + internal void ThrowIfNotCreated() { + if (nativePacket == IntPtr.Zero) + throw new InvalidOperationException("Packet not created"); + } + + public void SetFreeCallback(IntPtr callback) { + ThrowIfNotCreated(); + + Native.enet_packet_set_free_callback(nativePacket, callback); + } + + public void SetFreeCallback(PacketFreeCallback callback) { + ThrowIfNotCreated(); + + Native.enet_packet_set_free_callback(nativePacket, Marshal.GetFunctionPointerForDelegate(callback)); + } + + public void Create(byte[] data) { + if (data == null) + throw new ArgumentNullException("data"); + + Create(data, data.Length); + } + + public void Create(byte[] data, int length) { + Create(data, length, PacketFlags.None); + } + + public void Create(byte[] data, PacketFlags flags) { + Create(data, data.Length, flags); + } + + public void Create(byte[] data, int length, PacketFlags flags) { + if (data == null) + throw new ArgumentNullException("data"); + + if (length < 0 || length > data.Length) + throw new ArgumentOutOfRangeException("length"); + + nativePacket = Native.enet_packet_create(data, (IntPtr)length, flags); + } + + public void Create(IntPtr data, int length, PacketFlags flags) { + if (data == IntPtr.Zero) + throw new ArgumentNullException("data"); + + if (length < 0) + throw new ArgumentOutOfRangeException("length"); + + nativePacket = Native.enet_packet_create(data, (IntPtr)length, flags); + } + + public void Create(byte[] data, int offset, int length, PacketFlags flags) { + if (data == null) + throw new ArgumentNullException("data"); + + if (offset < 0) + throw new ArgumentOutOfRangeException("offset"); + + if (length < 0 || length > data.Length) + throw new ArgumentOutOfRangeException("length"); + + nativePacket = Native.enet_packet_create_offset(data, (IntPtr)length, (IntPtr)offset, flags); + } + + public void Create(IntPtr data, int offset, int length, PacketFlags flags) { + if (data == IntPtr.Zero) + throw new ArgumentNullException("data"); + + if (offset < 0) + throw new ArgumentOutOfRangeException("offset"); + + if (length < 0) + throw new ArgumentOutOfRangeException("length"); + + nativePacket = Native.enet_packet_create_offset(data, (IntPtr)length, (IntPtr)offset, flags); + } + + public void CopyTo(byte[] destination) { + if (destination == null) + throw new ArgumentNullException("destination"); + + Marshal.Copy(Data, destination, 0, Length); + } + } + + public class Host : IDisposable { + private IntPtr nativeHost; + + internal IntPtr NativeData { + get { + return nativeHost; + } + + set { + nativeHost = value; + } + } + + public void Dispose() { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) { + if (nativeHost != IntPtr.Zero) { + Native.enet_host_destroy(nativeHost); + nativeHost = IntPtr.Zero; + } + } + + ~Host() { + Dispose(false); + } + + public bool IsSet { + get { + return nativeHost != IntPtr.Zero; + } + } + + public uint PeersCount { + get { + ThrowIfNotCreated(); + + return Native.enet_host_get_peers_count(nativeHost); + } + } + + public uint PacketsSent { + get { + ThrowIfNotCreated(); + + return Native.enet_host_get_packets_sent(nativeHost); + } + } + + public uint PacketsReceived { + get { + ThrowIfNotCreated(); + + return Native.enet_host_get_packets_received(nativeHost); + } + } + + public uint BytesSent { + get { + ThrowIfNotCreated(); + + return Native.enet_host_get_bytes_sent(nativeHost); + } + } + + public uint BytesReceived { + get { + ThrowIfNotCreated(); + + return Native.enet_host_get_bytes_received(nativeHost); + } + } + + internal void ThrowIfNotCreated() { + if (nativeHost == IntPtr.Zero) + throw new InvalidOperationException("Host not created"); + } + + private static void ThrowIfChannelsExceeded(int channelLimit) { + if (channelLimit < 0 || channelLimit > Library.maxChannelCount) + throw new ArgumentOutOfRangeException("channelLimit"); + } + + public void Create() { + Create(null, 1, 0); + } + + public void Create(int bufferSize) { + Create(null, 1, 0, 0, 0, bufferSize); + } + + public void Create(Address? address, int peerLimit) { + Create(address, peerLimit, 0); + } + + public void Create(Address? address, int peerLimit, int channelLimit) { + Create(address, peerLimit, channelLimit, 0, 0, 0); + } + + public void Create(int peerLimit, int channelLimit) { + Create(null, peerLimit, channelLimit, 0, 0, 0); + } + + public void Create(int peerLimit, int channelLimit, uint incomingBandwidth, uint outgoingBandwidth) { + Create(null, peerLimit, channelLimit, incomingBandwidth, outgoingBandwidth, 0); + } + + public void Create(Address? address, int peerLimit, int channelLimit, uint incomingBandwidth, uint outgoingBandwidth) { + Create(address, peerLimit, channelLimit, incomingBandwidth, outgoingBandwidth, 0); + } + + public void Create(Address? address, int peerLimit, int channelLimit, uint incomingBandwidth, uint outgoingBandwidth, int bufferSize) { + if (nativeHost != IntPtr.Zero) + throw new InvalidOperationException("Host already created"); + + if (peerLimit < 0 || peerLimit > Library.maxPeers) + throw new ArgumentOutOfRangeException("peerLimit"); + + ThrowIfChannelsExceeded(channelLimit); + + if (address != null) { + var nativeAddress = address.Value.NativeData; + + nativeHost = Native.enet_host_create(ref nativeAddress, (IntPtr)peerLimit, (IntPtr)channelLimit, incomingBandwidth, outgoingBandwidth, bufferSize); + } else { + nativeHost = Native.enet_host_create(IntPtr.Zero, (IntPtr)peerLimit, (IntPtr)channelLimit, incomingBandwidth, outgoingBandwidth, bufferSize); + } + + if (nativeHost == IntPtr.Zero) + throw new InvalidOperationException("Host creation call failed"); + } + + public void PreventConnections(bool state) { + ThrowIfNotCreated(); + + Native.enet_host_prevent_connections(nativeHost, (byte)(state ? 1 : 0)); + } + + public void Broadcast(byte channelID, ref Packet packet) { + ThrowIfNotCreated(); + + packet.ThrowIfNotCreated(); + Native.enet_host_broadcast(nativeHost, channelID, packet.NativeData); + packet.NativeData = IntPtr.Zero; + } + + public void Broadcast(byte channelID, ref Packet packet, Peer excludedPeer) { + ThrowIfNotCreated(); + + packet.ThrowIfNotCreated(); + Native.enet_host_broadcast_exclude(nativeHost, channelID, packet.NativeData, excludedPeer.NativeData); + packet.NativeData = IntPtr.Zero; + } + + public void Broadcast(byte channelID, ref Packet packet, Peer[] peers) { + if (peers == null) + throw new ArgumentNullException("peers"); + + ThrowIfNotCreated(); + + packet.ThrowIfNotCreated(); + + if (peers.Length > 0) { + IntPtr[] nativePeers = ArrayPool.GetPointerBuffer(); + int nativeCount = 0; + + for (int i = 0; i < peers.Length; i++) { + if (peers[i].NativeData != IntPtr.Zero) { + nativePeers[nativeCount] = peers[i].NativeData; + nativeCount++; + } + } + + Native.enet_host_broadcast_selective(nativeHost, channelID, packet.NativeData, nativePeers, (IntPtr)nativeCount); + packet.NativeData = IntPtr.Zero; + } else { + packet.Dispose(); + + throw new ArgumentOutOfRangeException("Peers array can't be empty"); + } + } + + public int CheckEvents(out Event @event) { + ThrowIfNotCreated(); + + ENetEvent nativeEvent; + + var result = Native.enet_host_check_events(nativeHost, out nativeEvent); + + if (result <= 0) { + @event = default(Event); + + return result; + } + + @event = new Event(nativeEvent); + + return result; + } + + public Peer Connect(Address address) { + return Connect(address, 0, 0); + } + + public Peer Connect(Address address, int channelLimit) { + return Connect(address, channelLimit, 0); + } + + public Peer Connect(Address address, int channelLimit, uint data) { + ThrowIfNotCreated(); + ThrowIfChannelsExceeded(channelLimit); + + var nativeAddress = address.NativeData; + var peer = new Peer(Native.enet_host_connect(nativeHost, ref nativeAddress, (IntPtr)channelLimit, data)); + + if (peer.NativeData == IntPtr.Zero) + throw new InvalidOperationException("Host connect call failed"); + + return peer; + } + + public int Service(int timeout, out Event @event) { + if (timeout < 0) + throw new ArgumentOutOfRangeException("timeout"); + + ThrowIfNotCreated(); + + ENetEvent nativeEvent; + + var result = Native.enet_host_service(nativeHost, out nativeEvent, (uint)timeout); + + if (result <= 0) { + @event = default(Event); + + return result; + } + + @event = new Event(nativeEvent); + + return result; + } + + public void SetBandwidthLimit(uint incomingBandwidth, uint outgoingBandwidth) { + ThrowIfNotCreated(); + + Native.enet_host_bandwidth_limit(nativeHost, incomingBandwidth, outgoingBandwidth); + } + + public void SetChannelLimit(int channelLimit) { + ThrowIfNotCreated(); + ThrowIfChannelsExceeded(channelLimit); + + Native.enet_host_channel_limit(nativeHost, (IntPtr)channelLimit); + } + + public void SetMaxDuplicatePeers(ushort number) { + ThrowIfNotCreated(); + + Native.enet_host_set_max_duplicate_peers(nativeHost, number); + } + + public void SetInterceptCallback(IntPtr callback) { + ThrowIfNotCreated(); + + Native.enet_host_set_intercept_callback(nativeHost, callback); + } + + public void SetInterceptCallback(InterceptCallback callback) { + ThrowIfNotCreated(); + + Native.enet_host_set_intercept_callback(nativeHost, Marshal.GetFunctionPointerForDelegate(callback)); + } + + public void SetChecksumCallback(IntPtr callback) { + ThrowIfNotCreated(); + + Native.enet_host_set_checksum_callback(nativeHost, callback); + } + + public void SetChecksumCallback(ChecksumCallback callback) { + ThrowIfNotCreated(); + + Native.enet_host_set_checksum_callback(nativeHost, Marshal.GetFunctionPointerForDelegate(callback)); + } + + public void Flush() { + ThrowIfNotCreated(); + + Native.enet_host_flush(nativeHost); + } + } + + public struct Peer { + private IntPtr nativePeer; + private uint nativeID; + + internal IntPtr NativeData { + get { + return nativePeer; + } + + set { + nativePeer = value; + } + } + + internal Peer(IntPtr peer) { + nativePeer = peer; + nativeID = nativePeer != IntPtr.Zero ? Native.enet_peer_get_id(nativePeer) : 0; + } + + public bool IsSet { + get { + return nativePeer != IntPtr.Zero; + } + } + + public uint ID { + get { + return nativeID; + } + } + + public string IP { + get { + ThrowIfNotCreated(); + + byte[] ip = ArrayPool.GetByteBuffer(); + + if (Native.enet_peer_get_ip(nativePeer, ip, (IntPtr)ip.Length) == 0) + return Encoding.ASCII.GetString(ip, 0, ip.StringLength()); + else + return String.Empty; + } + } + + public ushort Port { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_port(nativePeer); + } + } + + public uint MTU { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_mtu(nativePeer); + } + } + + public PeerState State { + get { + return nativePeer == IntPtr.Zero ? PeerState.Uninitialized : Native.enet_peer_get_state(nativePeer); + } + } + + public uint RoundTripTime { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_rtt(nativePeer); + } + } + + public uint LastRoundTripTime { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_last_rtt(nativePeer); + } + } + + public uint LastSendTime { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_lastsendtime(nativePeer); + } + } + + public uint LastReceiveTime { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_lastreceivetime(nativePeer); + } + } + + public ulong PacketsSent { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_packets_sent(nativePeer); + } + } + + public ulong PacketsLost { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_packets_lost(nativePeer); + } + } + + public float PacketsThrottle { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_packets_throttle(nativePeer); + } + } + + public ulong BytesSent { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_bytes_sent(nativePeer); + } + } + + public ulong BytesReceived { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_bytes_received(nativePeer); + } + } + + public IntPtr Data { + get { + ThrowIfNotCreated(); + + return Native.enet_peer_get_data(nativePeer); + } + + set { + ThrowIfNotCreated(); + + Native.enet_peer_set_data(nativePeer, value); + } + } + + internal void ThrowIfNotCreated() { + if (nativePeer == IntPtr.Zero) + throw new InvalidOperationException("Peer not created"); + } + + public void ConfigureThrottle(uint interval, uint acceleration, uint deceleration, uint threshold) { + ThrowIfNotCreated(); + + Native.enet_peer_throttle_configure(nativePeer, interval, acceleration, deceleration, threshold); + } + + public bool Send(byte channelID, ref Packet packet) { + ThrowIfNotCreated(); + + packet.ThrowIfNotCreated(); + + return Native.enet_peer_send(nativePeer, channelID, packet.NativeData) == 0; + } + + public bool Receive(out byte channelID, out Packet packet) { + ThrowIfNotCreated(); + + IntPtr nativePacket = Native.enet_peer_receive(nativePeer, out channelID); + + if (nativePacket != IntPtr.Zero) { + packet = new Packet(nativePacket); + + return true; + } + + packet = default(Packet); + + return false; + } + + public void Ping() { + ThrowIfNotCreated(); + + Native.enet_peer_ping(nativePeer); + } + + public void PingInterval(uint interval) { + ThrowIfNotCreated(); + + Native.enet_peer_ping_interval(nativePeer, interval); + } + + public void Timeout(uint timeoutLimit, uint timeoutMinimum, uint timeoutMaximum) { + ThrowIfNotCreated(); + + Native.enet_peer_timeout(nativePeer, timeoutLimit, timeoutMinimum, timeoutMaximum); + } + + public void Disconnect(uint data) { + ThrowIfNotCreated(); + + Native.enet_peer_disconnect(nativePeer, data); + } + + public void DisconnectNow(uint data) { + ThrowIfNotCreated(); + + Native.enet_peer_disconnect_now(nativePeer, data); + } + + public void DisconnectLater(uint data) { + ThrowIfNotCreated(); + + Native.enet_peer_disconnect_later(nativePeer, data); + } + + public void Reset() { + ThrowIfNotCreated(); + + Native.enet_peer_reset(nativePeer); + } + } + + public static class Extensions { + public static int StringLength(this byte[] data) { + if (data == null) + throw new ArgumentNullException("data"); + + int i; + + for (i = 0; i < data.Length && data[i] != 0; i++); + + return i; + } + } + + public static class Library { + public const uint maxChannelCount = 0xFF; + public const uint maxPeers = 0xFFF; + public const uint maxPacketSize = 32 * 1024 * 1024; + public const uint throttleThreshold = 40; + public const uint throttleScale = 32; + public const uint throttleAcceleration = 2; + public const uint throttleDeceleration = 2; + public const uint throttleInterval = 5000; + public const uint timeoutLimit = 32; + public const uint timeoutMinimum = 5000; + public const uint timeoutMaximum = 30000; + public const uint version = (2 << 16) | (5 << 8) | (3); + + public static uint Time { + get { + return Native.enet_time_get(); + } + } + + public static bool Initialize() { + if (Native.enet_linked_version() != version) + throw new InvalidOperationException("Incompatible version"); + + return Native.enet_initialize() == 0; + } + + public static bool Initialize(Callbacks callbacks) { + if (callbacks == null) + throw new ArgumentNullException("callbacks"); + + if (Native.enet_linked_version() != version) + throw new InvalidOperationException("Incompatible version"); + + ENetCallbacks nativeCallbacks = callbacks.NativeData; + + return Native.enet_initialize_with_callbacks(version, ref nativeCallbacks) == 0; + } + + public static void Deinitialize() { + Native.enet_deinitialize(); + } + + public static ulong CRC64(IntPtr buffers, int bufferCount) { + return Native.enet_crc64(buffers, bufferCount); + } + } + + [SuppressUnmanagedCodeSecurity] + internal static class Native { + #if __IOS__ || UNITY_IOS && !UNITY_EDITOR + private const string nativeLibrary = "__Internal"; + #elif UNITY_EDITOR_LINUX || UNITY_STANDALONE_LINUX + private const string nativeLibrary = "libenet"; + #else + private const string nativeLibrary = "enet"; + #endif + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_initialize(); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_initialize_with_callbacks(uint version, ref ENetCallbacks inits); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_deinitialize(); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_linked_version(); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_time_get(); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong enet_crc64(IntPtr buffers, int bufferCount); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_address_set_ip(ref ENetAddress address, string ip); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_address_set_hostname(ref ENetAddress address, string hostName); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_address_get_ip(ref ENetAddress address, StringBuilder ip, IntPtr ipLength); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_address_get_hostname(ref ENetAddress address, StringBuilder hostName, IntPtr nameLength); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_create(byte[] data, IntPtr dataLength, PacketFlags flags); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_create(IntPtr data, IntPtr dataLength, PacketFlags flags); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_create_offset(byte[] data, IntPtr dataLength, IntPtr dataOffset, PacketFlags flags); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_create_offset(IntPtr data, IntPtr dataLength, IntPtr dataOffset, PacketFlags flags); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_packet_check_references(IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_get_data(IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_get_user_data(IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_packet_set_user_data(IntPtr packet, IntPtr userData); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_packet_get_length(IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_packet_set_free_callback(IntPtr packet, IntPtr callback); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_packet_dispose(IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_host_create(ref ENetAddress address, IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth, int bufferSize); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_host_create(IntPtr address, IntPtr peerLimit, IntPtr channelLimit, uint incomingBandwidth, uint outgoingBandwidth, int bufferSize); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_host_connect(IntPtr host, ref ENetAddress address, IntPtr channelCount, uint data); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_broadcast(IntPtr host, byte channelID, IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_broadcast_exclude(IntPtr host, byte channelID, IntPtr packet, IntPtr excludedPeer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_broadcast_selective(IntPtr host, byte channelID, IntPtr packet, IntPtr[] peers, IntPtr peersLength); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_host_service(IntPtr host, out ENetEvent @event, uint timeout); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_host_check_events(IntPtr host, out ENetEvent @event); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_channel_limit(IntPtr host, IntPtr channelLimit); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_bandwidth_limit(IntPtr host, uint incomingBandwidth, uint outgoingBandwidth); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_host_get_peers_count(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_host_get_packets_sent(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_host_get_packets_received(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_host_get_bytes_sent(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_host_get_bytes_received(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_set_max_duplicate_peers(IntPtr host, ushort number); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_set_intercept_callback(IntPtr host, IntPtr callback); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_set_checksum_callback(IntPtr host, IntPtr callback); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_flush(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_destroy(IntPtr host); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_host_prevent_connections(IntPtr host, byte state); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_throttle_configure(IntPtr peer, uint interval, uint acceleration, uint deceleration, uint threshold); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_id(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_peer_get_ip(IntPtr peer, byte[] ip, IntPtr ipLength); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ushort enet_peer_get_port(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_mtu(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern PeerState enet_peer_get_state(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_rtt(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_last_rtt(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_lastsendtime(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern uint enet_peer_get_lastreceivetime(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong enet_peer_get_packets_sent(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong enet_peer_get_packets_lost(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern float enet_peer_get_packets_throttle(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong enet_peer_get_bytes_sent(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong enet_peer_get_bytes_received(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_peer_get_data(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_set_data(IntPtr peer, IntPtr data); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern int enet_peer_send(IntPtr peer, byte channelID, IntPtr packet); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr enet_peer_receive(IntPtr peer, out byte channelID); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_ping(IntPtr peer); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_ping_interval(IntPtr peer, uint pingInterval); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_timeout(IntPtr peer, uint timeoutLimit, uint timeoutMinimum, uint timeoutMaximum); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_disconnect(IntPtr peer, uint data); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_disconnect_now(IntPtr peer, uint data); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_disconnect_later(IntPtr peer, uint data); + + [DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)] + internal static extern void enet_peer_reset(IntPtr peer); + } +} diff --git a/ENet.cs.meta b/ENet.cs.meta new file mode 100644 index 0000000..99095fa --- /dev/null +++ b/ENet.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6f114d39fb3bd7f4c8f99726cddb71fe \ No newline at end of file diff --git a/Shazbot.ENet.asmdef b/Shazbot.ENet.asmdef new file mode 100644 index 0000000..c398e20 --- /dev/null +++ b/Shazbot.ENet.asmdef @@ -0,0 +1,14 @@ +{ + "name": "Shazbot.ENet", + "rootNamespace": "ENet", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Shazbot.ENet.asmdef.meta b/Shazbot.ENet.asmdef.meta new file mode 100644 index 0000000..896d7fe --- /dev/null +++ b/Shazbot.ENet.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 53c0306dcb999d443b15d06b95419929 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/enet.dll b/enet.dll new file mode 100644 index 0000000..6877529 --- /dev/null +++ b/enet.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:491d4118cf39a75871f0feb898fd326b4d8ce88b07d6cfbf12df2113b7af1a54 +size 42496 diff --git a/enet.dll.meta b/enet.dll.meta new file mode 100644 index 0000000..25d4f10 --- /dev/null +++ b/enet.dll.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 99db336fe23dc4e4c8c6598c0bfb2406 \ No newline at end of file diff --git a/libenet.so b/libenet.so new file mode 100644 index 0000000..9d51089 --- /dev/null +++ b/libenet.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0659e5aed9e7dacfec625678bc41618f7e30f8a301fde0abbb7a83940b4b34e0 +size 62600 diff --git a/libenet.so.meta b/libenet.so.meta new file mode 100644 index 0000000..0865f53 --- /dev/null +++ b/libenet.so.meta @@ -0,0 +1,50 @@ +fileFormatVersion: 2 +guid: 1941b772d194c0d459330ae2a6848b43 +PluginImporter: + externalObjects: {} + serializedVersion: 3 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + Android: + enabled: 0 + settings: + Is16KbAligned: false + Any: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 1 + Exclude Win: 0 + Exclude Win64: 0 + Editor: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + Linux64: + enabled: 1 + settings: + CPU: x86_64 + OSXUniversal: + enabled: 0 + settings: + CPU: None + Win: + enabled: 1 + settings: + CPU: x86 + Win64: + enabled: 1 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/package.json b/package.json new file mode 100644 index 0000000..c08d0ef --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "ru.shazbot.enet", + "version": "2.5.3", + "displayName": "ENet", + "description": "ENet (libenet) for Unity.", + "licensesUrl": "https://github.com/nxrighthere/ENet-CSharp/blob/master/LICENSE", + "keywords": [ + "enet", + "libenet" + ], + "author": { + "name": "Alexander Filippov", + "email": "alexander@shazbot.ru", + "url": "https://shazbot.ru/" + }, + "dependencies": { } +} diff --git a/package.json.meta b/package.json.meta new file mode 100644 index 0000000..dd9ce8f --- /dev/null +++ b/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5c57d367673df374a805c6fb2344a8b4 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: