1 /** 2 Copyright: Copyright (c) 2015-2017 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) { warningf("Exception while reading stdin: %s", e); } 54 } 55 56 void readStdin() 57 { 58 if (!stdin.isOpen || stdin.eof || stdin.error) return; 59 60 auto size = stdin.size; 61 if (size > 0 && size != ulong.max) 62 { 63 import std.regex : ctRegex, splitter; 64 import std.algorithm : min; 65 import std.array : array; 66 67 size_t charsToRead = min(size, buf.length); 68 char[] data = stdin.rawRead(buf[0..charsToRead]); 69 auto splittedLines = splitter(data, ctRegex!"(\r\n|\r|\n|\v|\f)").array; 70 71 while (splittedLines.length > 1) 72 { 73 char[] command = splittedLines[0]; 74 splittedLines = splittedLines[1..$]; 75 76 ExecResult res = commandPlugin.execute(command, SessionId(0)); 77 78 if (res.status == ExecStatus.notRegistered) 79 { 80 warningf("Unknown command '%s'", command); 81 } 82 else if (res.status == ExecStatus.error) 83 warningf("Error executing command '%s': %s", command, res.error); 84 } 85 86 if (splittedLines.length == 1) 87 stdin.seek(-cast(long)splittedLines[0].length); 88 } 89 } 90 }