#region using System; #endregion namespace ENet { public unsafe class Host : IDisposable { private Native.ENetHost* _host; public bool IsSet { get { return _host != null; } } public Native.ENetHost* NativeData { get { return _host; } set { _host = value; } } #region IDisposable Members public void Dispose() { Dispose(true); } #endregion ~Host() { Dispose(false); } private void CheckChannelLimit(int channelLimit) { if (channelLimit < 0 || channelLimit > Native.ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { throw new ArgumentOutOfRangeException("channelLimit"); } } private void CheckCreated() { if (_host == null) { throw new InvalidOperationException("Not created."); } } public void Create(ushort port, int peerLimit) { var address = new Address(); address.Port = port; Create(address, peerLimit); } 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); } public void Create(Address? address, int peerLimit, int channelLimit, uint incomingBandwidth, uint outgoingBandwidth) { if (_host != null) { throw new InvalidOperationException("Already created."); } if (peerLimit < 0 || peerLimit > Native.ENET_PROTOCOL_MAXIMUM_PEER_ID) { throw new ArgumentOutOfRangeException("peerLimit"); } CheckChannelLimit(channelLimit); if (address != null) { var nativeAddress = address.Value.NativeData; _host = Native.enet_host_create(ref nativeAddress, (IntPtr) peerLimit, (IntPtr) channelLimit, incomingBandwidth, outgoingBandwidth); } else { _host = Native.enet_host_create(null, (IntPtr) peerLimit, (IntPtr) channelLimit, incomingBandwidth, outgoingBandwidth); } if (_host == null) { throw new ENetException(0, "Host creation call failed."); } } protected virtual void Dispose(bool disposing) { if (_host != null) { Native.enet_host_destroy(_host); _host = null; } } public void Broadcast(byte channelID, ref Packet packet) { CheckCreated(); packet.CheckCreated(); Native.enet_host_broadcast(_host, channelID, packet.NativeData); packet.NativeData = null; // Broadcast automatically clears this. } public void CompressWithRangeCoder() { CheckCreated(); Native.enet_host_compress_with_range_coder(_host); } public void DoNotCompress() { CheckCreated(); Native.enet_host_compress(_host, null); } public int CheckEvents(out Event @event) { CheckCreated(); Native.ENetEvent nativeEvent; var ret = Native.enet_host_check_events(_host, out nativeEvent); if (ret <= 0) { @event = new Event(); return ret; } @event = new Event(nativeEvent); return ret; } public Peer Connect(Address address, int channelLimit, uint data) { CheckCreated(); CheckChannelLimit(channelLimit); var nativeAddress = address.NativeData; var peer = new Peer(Native.enet_host_connect(_host, ref nativeAddress, (IntPtr) channelLimit, data)); if (peer.NativeData == null) { throw new ENetException(0, "Host connect call failed."); } return peer; } public void Flush() { CheckCreated(); Native.enet_host_flush(_host); } public int Service(int timeout) { if (timeout < 0) { throw new ArgumentOutOfRangeException("timeout"); } CheckCreated(); return Native.enet_host_service(_host, null, (uint) timeout); } public int Service(int timeout, out Event @event) { if (timeout < 0) { throw new ArgumentOutOfRangeException("timeout"); } CheckCreated(); Native.ENetEvent nativeEvent; var ret = Native.enet_host_service(_host, out nativeEvent, (uint) timeout); if (ret <= 0) { @event = new Event(); return ret; } @event = new Event(nativeEvent); return ret; } public void SetBandwidthLimit(uint incomingBandwidth, uint outgoingBandwidth) { CheckCreated(); Native.enet_host_bandwidth_limit(_host, incomingBandwidth, outgoingBandwidth); } public void SetChannelLimit(int channelLimit) { CheckChannelLimit(channelLimit); CheckCreated(); Native.enet_host_channel_limit(_host, (IntPtr) channelLimit); } } }