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