1 /**
2 Copyright: Copyright (c) 2015-2018 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module voxelman.remotecontrol.plugin;
7 
8 import std.stdio;
9 import voxelman.log;
10 import std.traits : Select;
11 
12 import pluginlib;
13 import voxelman.core.events;
14 import voxelman.eventdispatcher.plugin;
15 import voxelman.command.plugin;
16 import voxelman.server.plugin;
17 
18 
19 final class RemoteControl(bool clientSide) : IPlugin
20 {
21 	alias CommandPlugin = Select!(clientSide, CommandPluginClient, CommandPluginServer);
22 
23 	// IPlugin stuff
24 	mixin IdAndSemverFrom!"voxelman.remotecontrol.plugininfo";
25 	private EventDispatcherPlugin evDispatcher;
26 	private CommandPlugin commandPlugin;
27 	private char[] buf;
28 
29 	override void preInit() {
30 		buf = new char[](2048);
31 	}
32 
33 	override void init(IPluginManager pluginman)
34 	{
35 		evDispatcher = pluginman.getPlugin!EventDispatcherPlugin;
36 		commandPlugin = pluginman.getPlugin!CommandPlugin;
37 		bool enable = true;
38 
39 		static if (!clientSide)
40 		{
41 			ServerPlugin serverPlugin = pluginman.findPlugin!ServerPlugin;
42 			bool serverPresent = serverPlugin !is null;
43 			enable = serverPresent && (serverPlugin.mode == ServerMode.standalone);
44 		}
45 
46 		if (enable)
47 			evDispatcher.subscribeToEvent(&onPreUpdateEvent);
48 	}
49 
50 	void onPreUpdateEvent(ref PreUpdateEvent event)
51 	{
52 		try readStdin();
53 		catch (Exception e) {
54 			//warningf("Exception while reading stdin: %s", e);
55 		}
56 	}
57 
58 	void readStdin()
59 	{
60 		if (!stdin.isOpen || stdin.eof || stdin.error) return;
61 
62 		auto size = stdin.size;
63 		if (size > 0 && size != ulong.max)
64 		{
65 			import std.regex : regex, splitter;
66 			import std.algorithm : min;
67 			import std.array : array;
68 
69 			size_t charsToRead = min(size, buf.length);
70 			char[] data = stdin.rawRead(buf[0..charsToRead]);
71 			auto splittedLines = splitter(data, regex("(\r\n|\r|\n|\v|\f)")).array;
72 
73 			while (splittedLines.length > 1)
74 			{
75 				char[] command = splittedLines[0];
76 				splittedLines = splittedLines[1..$];
77 
78 				commandPlugin.execute(command, CommandSourceType.localLauncher, SessionId(0));
79 				info(commandPlugin.commandTextOutput.text);
80 			}
81 
82 			if (splittedLines.length == 1)
83 				stdin.seek(-cast(long)splittedLines[0].length);
84 		}
85 	}
86 }