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