1 /** 2 Copyright: Copyright (c) 2016-2017 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module enginestarter; 8 9 import std.file : mkdirRecurse; 10 import std.path : buildPath; 11 import std.getopt; 12 import core.thread : Thread, thread_joinAll; 13 import voxelman.log; 14 import pluginlib; 15 import pluginlib.plugininforeader : filterEnabledPlugins; 16 import pluginlib.pluginmanager; 17 18 import voxelman.cons; 19 import test.cons; 20 21 22 struct EngineStarter 23 { 24 enum AppType { client, server, combined } 25 26 void start(string[] args) 27 { 28 AppType appType = AppType.combined; 29 std.getopt.getopt(args, 30 std.getopt.config.passThrough, 31 "app", &appType); 32 33 setupLogs(appType); 34 scope(exit) closeBinLog(); 35 36 final switch(appType) with(AppType) 37 { 38 case client: startClient(args); break; 39 case server: startServer(args, ServerMode.standalone); break; 40 case combined: startCombined(args); break; 41 } 42 43 waitForThreads(); 44 } 45 46 void setupLogs(AppType appType, string logsFolder = "../logs") 47 { 48 mkdirRecurse(logsFolder); 49 enum textFormat = ".log"; 50 enum binFormat = ".bin"; 51 52 string name; 53 final switch(appType) with(AppType) 54 { 55 case client: name = "client"; break; 56 case server: name = "server"; break; 57 case combined: name = "client"; break; 58 } 59 setupLogger(buildPath(logsFolder, name ~ textFormat)); 60 initBinLog(buildPath(logsFolder, name ~ binFormat)); 61 } 62 63 void startServer(string[] args, ServerMode serverMode) 64 { 65 auto pluginman = new PluginManager; 66 foreach(p; pluginRegistry.serverPlugins.byValue.filterEnabledPlugins(args)) 67 pluginman.registerPlugin(p); 68 pluginman.initPlugins(); 69 pluginRegistry.serverMain(args, serverMode); 70 } 71 72 void startClient(string[] args) 73 { 74 auto pluginman = new PluginManager; 75 foreach(p; pluginRegistry.clientPlugins.byValue.filterEnabledPlugins(args)) 76 pluginman.registerPlugin(p); 77 pluginman.initPlugins(); 78 pluginRegistry.clientMain(args); 79 } 80 81 void startCombined(string[] args) 82 { 83 import voxelman.client.servercontrol : stopServer; 84 85 void exec() 86 { 87 infof("Server thread: %s", Thread.getThis.id); 88 try { 89 startServer(args, ServerMode.internal); 90 } catch(Throwable t) { 91 criticalf("Server failed with error"); 92 criticalf("%s", t.msg); 93 criticalf("%s", t); 94 } 95 } 96 97 Thread serverThread = new Thread(&exec); 98 serverThread.start(); 99 100 infof("Client thread: %s", Thread.getThis.id); 101 startClient(args); 102 stopServer(); 103 } 104 105 void waitForThreads() 106 { 107 thread_joinAll(); 108 infof("[Stopped]"); 109 } 110 }