1 /** 2 Copyright: Copyright (c) 2015-2016 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module voxelman.net.plugin; 8 9 import derelict.enet.enet; 10 11 import pluginlib; 12 public import netlib; 13 import derelict.enet.enet; 14 15 import voxelman.core.config; 16 import voxelman.net.events; 17 import voxelman.core.events; 18 import voxelman.core.packets; 19 import voxelman.net.packets; 20 21 import voxelman.eventdispatcher.plugin; 22 import voxelman.config.configmanager; 23 24 shared static this() 25 { 26 pluginRegistry.regClientPlugin(new NetClientPlugin); 27 pluginRegistry.regServerPlugin(new NetServerPlugin); 28 } 29 30 mixin template NetCommon() 31 { 32 mixin IdAndSemverFrom!(voxelman.net.plugininfo); 33 private EventDispatcherPlugin evDispatcher; 34 35 override void preInit() { 36 import voxelman.utils.libloader; 37 loadEnet([getLibName(BUILD_TO_ROOT_PATH, "enet")]); 38 39 connection.connectHandler = &onConnect; 40 connection.disconnectHandler = &onDisconnect; 41 voxelman.net.packets.registerPackets(connection); 42 voxelman.core.packets.registerPackets(connection); 43 } 44 45 override void init(IPluginManager pluginman) { 46 evDispatcher = pluginman.getPlugin!EventDispatcherPlugin; 47 } 48 } 49 50 final class NetClientPlugin : IPlugin 51 { 52 mixin NetCommon; 53 54 BaseClient connection; 55 alias connection this; 56 57 this() { 58 connection = new class BaseClient{}; 59 } 60 61 void onConnect(ref ENetEvent event) { 62 evDispatcher.postEvent(ThisClientConnectedEvent()); 63 } 64 65 void onDisconnect(ref ENetEvent event) { 66 event.peer.data = null; 67 evDispatcher.postEvent(ThisClientDisconnectedEvent(event.data)); 68 } 69 } 70 71 final class NetServerPlugin : IPlugin 72 { 73 private: 74 ConfigOption portOpt; 75 EventDispatcherPlugin evDispatcher; 76 77 public: 78 mixin NetCommon; 79 80 BaseServer connection; 81 alias connection this; 82 83 override void registerResources(IResourceManagerRegistry resmanRegistry) 84 { 85 ConfigManager config = resmanRegistry.getResourceManager!ConfigManager; 86 portOpt = config.registerOption!ushort("port", 1234); 87 } 88 89 this() 90 { 91 connection = new class BaseServer{}; 92 } 93 94 override void init(IPluginManager pluginman) 95 { 96 evDispatcher = pluginman.getPlugin!EventDispatcherPlugin; 97 evDispatcher.subscribeToEvent(&handleGameStartEvent); 98 evDispatcher.subscribeToEvent(&onPreUpdateEvent); 99 evDispatcher.subscribeToEvent(&onPostUpdateEvent); 100 evDispatcher.subscribeToEvent(&handleGameStopEvent); 101 } 102 103 override void postInit() 104 { 105 //connection.shufflePackets(); 106 connection.printPacketMap(); 107 } 108 109 void handleGameStartEvent(ref GameStartEvent event) 110 { 111 ConnectionSettings settings = {null, 32, 2, 0, 0}; 112 connection.start(settings, ENET_HOST_ANY, portOpt.get!ushort); 113 static if (ENABLE_RLE_PACKET_COMPRESSION) 114 enet_host_compress_with_range_coder(connection.host); 115 } 116 117 void onConnect(ref ENetEvent event) { 118 auto clientId = connection.clientStorage.addClient(event.peer); 119 event.peer.data = cast(void*)clientId; 120 121 evDispatcher.postEvent(ClientConnectedEvent(clientId)); 122 } 123 124 void onDisconnect(ref ENetEvent event) { 125 ClientId clientId = cast(ClientId)event.peer.data; 126 event.peer.data = null; 127 connection.clientStorage.removeClient(clientId); 128 evDispatcher.postEvent(ClientDisconnectedEvent(clientId)); 129 } 130 131 void onPreUpdateEvent(ref PreUpdateEvent event) 132 { 133 connection.update(); 134 } 135 136 void onPostUpdateEvent(ref PostUpdateEvent event) 137 { 138 connection.flush(); 139 } 140 141 void handleGameStopEvent(ref GameStopEvent event) 142 { 143 connection.sendToAll(MessagePacket(0, "Stopping server")); 144 connection.disconnectAll(); 145 while (connection.clientStorage.length) 146 { 147 connection.update(); 148 } 149 connection.stop(); 150 } 151 }