commit 2f3ffa555890fea299e1725ecc81e7473aedc08b Author: Alexander Filippov Date: Wed May 13 13:28:41 2026 +0200 Initial commit. 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: