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 }