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 module voxelman.remotecontrol.plugin;
7 
8 import std.stdio;
9 import std.experimental.logger;
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 
17 shared static this()
18 {
19 	pluginRegistry.regClientPlugin(new RemoteControl!true);
20 	pluginRegistry.regServerPlugin(new RemoteControl!false);
21 }
22 
23 final class RemoteControl(bool clientSide) : IPlugin
24 {
25 	alias CommandPlugin = Select!(clientSide, CommandPluginClient, CommandPluginServer);
26 
27 	// IPlugin stuff
28 	mixin IdAndSemverFrom!(voxelman.remotecontrol.plugininfo);
29 	private EventDispatcherPlugin evDispatcher;
30 	private CommandPlugin commandPlugin;
31 	private char[] buf;
32 
33 	override void preInit() {
34 		buf = new char[](2048);
35 	}
36 	override void init(IPluginManager pluginman)
37 	{
38 		evDispatcher = pluginman.getPlugin!EventDispatcherPlugin;
39 		evDispatcher.subscribeToEvent(&onPreUpdateEvent);
40 		commandPlugin = pluginman.getPlugin!CommandPlugin;
41 	}
42 
43 	void onPreUpdateEvent(ref PreUpdateEvent event)
44 	{
45 		try readStdin();
46 		catch (Exception e) { warningf("Exception while reading stdin: %s", e); }
47 	}
48 
49 	void readStdin()
50 	{
51 		if (!stdin.isOpen || stdin.eof || stdin.error) return;
52 
53 		auto size = stdin.size;
54 		if (size > 0 && size != ulong.max)
55 		{
56 			import std.regex : ctRegex, splitter;
57 			import std.algorithm : min;
58 			import std.array : array;
59 
60 			size_t charsToRead = min(size, buf.length);
61 			char[] data = stdin.rawRead(buf[0..charsToRead]);
62 			auto splittedLines = splitter(data, ctRegex!"(\r\n|\r|\n|\v|\f)").array;
63 
64 			while (splittedLines.length > 1)
65 			{
66 				char[] command = splittedLines[0];
67 				splittedLines = splittedLines[1..$];
68 
69 				ExecResult res = commandPlugin.execute(command, ClientId(0));
70 
71 				if (res.status == ExecStatus.notRegistered)
72 				{
73 					warningf("Unknown command '%s'", command);
74 				}
75 				else if (res.status == ExecStatus.error)
76 					warningf("Error executing command '%s': %s", command, res.error);
77 			}
78 
79 			if (splittedLines.length == 1)
80 				stdin.seek(-cast(long)splittedLines[0].length);
81 		}
82 	}
83 }