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 }