1 module gfm.enet.enet; 2 3 import derelict.enet.enet; 4 import derelict.util.exception; 5 6 static if( __VERSION__ >= 2067 ) 7 import std.experimental.logger; 8 else 9 import std.historical.logger; 10 11 12 /// General ENet exception thrown for all cases. 13 final class ENetException : Exception 14 { 15 @safe pure nothrow this(string message, string file =__FILE__, size_t line = __LINE__, Throwable next = null) 16 { 17 super(message, file, line, next); 18 } 19 } 20 21 /// Owns the loader, logging, keyboard state... 22 /// This object is passed around to other ENet wrapper objects 23 /// to ensure library loading. 24 final class ENet 25 { 26 public 27 { 28 /// Loads DerelictENet and initializes the ENet library. 29 /// Throws: ENetException when enet_initialize fails. 30 this(Logger logger = null) 31 { 32 _logger = logger is null ? new NullLogger() : logger; 33 34 ShouldThrow missingSymFunc( string symName ) 35 { 36 // Supports from libenet 1.3.3 to 1.3.11+ 37 // Obviously we should take extras care in gfm:enet 38 // not to strictly rely on these functions. 39 40 if (symName == "enet_linked_version") 41 return ShouldThrow.No; 42 43 if (symName == "enet_socket_get_address") 44 return ShouldThrow.No; 45 46 if (symName == "enet_socket_get_option") 47 return ShouldThrow.No; 48 49 if (symName == "enet_socket_shutdown") 50 return ShouldThrow.No; 51 52 if (symName == "enet_host_random_seed") 53 return ShouldThrow.No; 54 55 if (symName == "enet_peer_ping_interval") 56 return ShouldThrow.No; 57 58 if (symName == "enet_peer_timeout") 59 return ShouldThrow.No; 60 61 if (symName == "enet_peer_on_connect") 62 return ShouldThrow.No; 63 64 if (symName == "enet_peer_on_disconnect") 65 return ShouldThrow.No; 66 67 // Any other missing symbol should throw. 68 return ShouldThrow.Yes; 69 } 70 71 DerelictENet.missingSymbolCallback = &missingSymFunc; 72 73 try 74 DerelictENet.load(); 75 catch(DerelictException e) 76 throw new ENetException(e.msg); 77 78 int errCode = enet_initialize(); 79 if(errCode < 0) 80 throw new ENetException("enet_initialize failed"); 81 82 _enetInitialized = true; 83 } 84 85 ~this() 86 { 87 close(); 88 } 89 90 /// Deinitializes the ENet library and unloads DerelictENet. 91 void close() 92 { 93 if(_enetInitialized) 94 { 95 enet_deinitialize(); 96 DerelictENet.unload(); 97 _enetInitialized = false; 98 } 99 } 100 } 101 102 package 103 { 104 Logger _logger; 105 } 106 107 private 108 { 109 bool _enetInitialized = false; 110 111 } 112 }