Browse Source

command event, basic snuvi script event handling

Kajetan Johannes Hammerle 3 months ago
parent
commit
72d366c32d

+ 18 - 1
resources/scripts/test.snuvi

@@ -1,5 +1,22 @@
 void main() {
-    for(int i = 0; i < 10; i++) {
+    for(int i = 0; i < 5; i++) {
         print("HaࠠI Th𐀠eröüäe\n");
     }
+    print("----------\n");
+    while(true) {
+        wait();
+        print("Wusi\n");
+        if(getEvent() != 1) {
+            continue;
+        }
+        print("Command Event: \n");
+        int** data = getArguments();
+        for(int i = 0; i < length(data); i++) {
+            print(data[i]);
+            print("\n");
+            delete data[i];
+        }
+        delete data;
+        print("\n");
+    }
 }

+ 0 - 1
server/Main.cpp

@@ -7,7 +7,6 @@
 #include "utils/Clock.h"
 
 int main() {
-    Snuvi::init();
     ENet enet;
     if(enet.init()) {
         std::cout << "cannot initialize enet\n";

+ 44 - 2
server/commands/CommandManager.cpp

@@ -1,3 +1,4 @@
+#include <cstring>
 #include <iostream>
 
 #include "common/network/Packets.h"
@@ -28,12 +29,46 @@ static void commandSay(ServerState& sc, const CommandArguments& args) {
     std::cout << s << '\n';
 }
 
+static void helpScript() {
+    std::cout << "/script start <script>\n";
+    std::cout << "/script term\n";
+}
+
 static void commandScript(ServerState&, const CommandArguments& args) {
     if(args.getLength() < 2) {
-        std::cout << "/start <script>\n";
+        helpScript();
+    } else if(strcmp(args[1], "start") == 0) {
+        if(args.getLength() < 3) {
+            std::cout << "/script start <script>\n";
+            return;
+        }
+        Snuvi::start(args[2]);
+    } else if(strcmp(args[1], "term") == 0) {
+        Snuvi::termAll();
+        std::cout << "all scripts were terminated\n";
+    } else {
+        helpScript();
+    }
+}
+
+static CommandArguments commandArguments = RawCommand();
+
+static void getArguments(Script* sc) {
+    int length = commandArguments.getLength();
+    Pointer p;
+    p.offset = 0;
+    p.array = asAllocate(&sc->arrays, sizeof(Pointer), length);
+    sPushPointer(sc, &p);
+    SnuviArray* array = asGet(&sc->arrays, p.array);
+    if(array == nullptr) {
+        sError(sc, "cannot allocate string memory");
         return;
     }
-    Snuvi::start(args[1]);
+    Pointer* texts = static_cast<Pointer*>(array->data);
+    for(int i = 0; i < length; i++) {
+        Pointer text = Snuvi::toString(sc, commandArguments[i]);
+        memcpy(texts + i, &text, sizeof(Pointer));
+    }
 }
 
 CommandManager::CommandManager() {
@@ -41,6 +76,11 @@ CommandManager::CommandManager() {
     commands.add("stop", commandStop);
     commands.add("say", commandSay);
     commands.add("script", commandScript);
+
+    DataType type = dtText();
+    dtDereference(&type);
+    Snuvi::initFunction("getArguments", type, getArguments);
+    Snuvi::addFunction();
 }
 
 void CommandManager::execute(ServerState& sc, const RawCommand& rawCommand) {
@@ -53,6 +93,8 @@ void CommandManager::execute(ServerState& sc, const RawCommand& rawCommand) {
     CommandName command(args[0]);
     Command* c = commands.search(command);
     if(c == nullptr) {
+        commandArguments = args;
+        Snuvi::callEvent(Snuvi::Event::COMMAND);
         std::cout << "Unknown command: '" << command << "'\n";
         return;
     }

+ 3 - 5
server/commands/CommandManager.h

@@ -6,15 +6,13 @@
 #include "utils/HashMap.h"
 
 class CommandManager {
+    typedef void (*Command)(ServerState&, const CommandArguments&);
+    HashMap<CommandName, Command> commands;
+
 public:
     CommandManager();
 
     void execute(ServerState& sc, const RawCommand& rawCommand);
-
-private:
-    typedef void (*Command)(ServerState&, const CommandArguments&);
-
-    HashMap<CommandName, Command> commands;
 };
 
 #endif

+ 118 - 23
server/snuviscript/Snuvi.cpp

@@ -3,11 +3,10 @@
 #include "libraries/Math.h"
 #include "libraries/Time.h"
 #include "tokenizer/Tokenizer.h"
+#include "utils/HashMap.h"
 #include "utils/StringBuffer.h"
 #include "vm/Script.h"
 
-static Function function;
-
 static const char* unicode(int32 c) {
     static char buffer[5];
     int index = 0;
@@ -47,39 +46,65 @@ static void printString(Script* sc) {
     }
 }
 
+static void printInt32(Script* sc) {
+    int32 i;
+    if(sPopInt32(sc, &i)) {
+        printf("%d", i);
+    }
+}
+
+static void wait(Script* sc) {
+    sError(sc, "w");
+}
+
+static Snuvi::Event event = Snuvi::Event::NONE;
+
+static void getEvent(Script* sc) {
+    sPushInt32(sc, event);
+}
+
 static void initPrinter() {
-    Snuvi::initFunction("print", printString);
-    Snuvi::addStringArgument();
+    Snuvi::initFunction("print", dtVoid(), printString);
+    Snuvi::addArgument(dtConst(dtText()));
+    Snuvi::addFunction();
+    Snuvi::initFunction("print", dtVoid(), printInt32);
+    Snuvi::addArgument(dtInt32());
     Snuvi::addFunction();
 }
 
-struct Init {
-    Init() {
+struct Scripts {
+    int scriptId = 0;
+    HashMap<int, Script*> scripts;
+
+    Scripts() {
         gfsInit();
         gstsInit();
         lTimeRegister();
         lMathRegister();
         initPrinter();
+        Snuvi::initFunction("wait", dtVoid(), wait);
+        Snuvi::addFunction();
+        Snuvi::initFunction("getEvent", dtInt32(), getEvent);
+        Snuvi::addFunction();
     }
 
-    ~Init() {
+    ~Scripts() {
         gfsDelete();
         gstsDelete();
+        Snuvi::termAll();
     }
 };
 
-void Snuvi::init() {
-    static Init init;
-}
+static Scripts scripts;
+static Function function;
 
-void Snuvi::initFunction(const char* name, ScriptFunction sf) {
-    gfInit(&function, name, dtVoid(), sf);
+void Snuvi::initFunction(const char* name, DataType returnType,
+                         ScriptFunction sf) {
+    gfInit(&function, name, returnType, sf);
 }
 
-void Snuvi::addStringArgument() {
-    DataType string = dtConst(dtInt32());
-    dtDereference(&string);
-    gfAddArgument(&function, string);
+void Snuvi::addArgument(DataType type) {
+    gfAddArgument(&function, type);
 }
 
 void Snuvi::addFunction() {
@@ -91,22 +116,92 @@ static void logError(const char* msg, int line) {
     printf("line: %d\n", line);
 }
 
-void Snuvi::start(const char* path) {
+static bool runScript(Script* script) {
+    sRun(script);
+    if(script->error[0] == 'w' && script->error[1] == '\0') {
+        script->error[0] = '\0';
+        return false;
+    } else if(script->error[0] != '\0') {
+        logError(script->error, script->line);
+        return true;
+    }
+    return script->readIndex >= script->code->length;
+}
+
+int Snuvi::start(const char* path) {
     StringBuffer<256> s("resources/scripts/");
     s.append(path).append(".snuvi");
     if(tTokenize(s)) {
         logError(tGetError(), tGetLine());
-        return;
+        return -1;
     }
     ByteCode* code = cCompile();
     if(code == nullptr) {
         logError(cGetError(), cGetLine());
-        return;
+        return -1;
     }
     Script* script = sInit(code);
-    sRun(script);
-    if(script->error[0] != '\0') {
-        logError(script->error, script->line);
+    if(runScript(script)) {
+        sDelete(script);
+        return -1;
+    }
+    int id = scripts.scriptId++;
+    scripts.scripts.tryEmplace(id, script);
+    return id;
+}
+
+void Snuvi::termAll() {
+    for(auto& entry : scripts.scripts) {
+        sDelete(entry.value);
+    }
+    scripts.scripts.clear();
+}
+
+void Snuvi::callEvent(Event e) {
+    event = e;
+    for(auto& entry : scripts.scripts) {
+        if(runScript(entry.value)) {
+            sDelete(entry.value);
+            scripts.scripts.remove(entry.getKey());
+        }
+    }
+}
+
+static int32 readChar(int& index, const char* s) {
+    if(s[index] == '\0') {
+        return '\0';
+    }
+    return s[index++];
+}
+
+Pointer Snuvi::toString(Script* sc, const char* s) {
+    List<int> data;
+    int index = 0;
+    while(s[index] != '\0') {
+        int32 c = readChar(index, s);
+        if((c & 0xE0) == 0xC0) {
+            c = ((c & 0x1F) << 6) | (readChar(index, s) & 0x3F);
+        } else if((c & 0xF0) == 0xE0) {
+            c = ((c & 0xF) << 12) | ((readChar(index, s) & 0x3F) << 6);
+            c |= readChar(index, s) & 0x3F;
+        } else if((c & 0xF8) == 0xF0) {
+            c = ((c & 0x7) << 18) | ((readChar(index, s) & 0x3F) << 12);
+            c |= (readChar(index, s) & 0x3F) << 6;
+            c |= readChar(index, s) & 0x3F;
+        }
+        data.add(c);
+    }
+    Pointer p;
+    p.offset = 0;
+    p.array = asAllocate(&sc->arrays, sizeof(int32), data.getLength());
+    printf("%d wsdfdg\n", data.getLength());
+    SnuviArray* array = asGet(&sc->arrays, p.array);
+    if(array == nullptr) {
+        sError(sc, "cannot allocate string memory");
+        p.offset = -1;
+        p.array = -1;
+    } else {
+        memcpy(array->data, data.begin(), sizeof(int32) * data.getLength());
     }
-    sDelete(script);
+    return p;
 }

+ 9 - 4
server/snuviscript/Snuvi.h

@@ -2,15 +2,20 @@
 #define SNUVI_H
 
 #include "utils/Functions.h"
+#include "utils/StringBuffer.h"
 
 namespace Snuvi {
-    void init();
+    enum Event { NONE, COMMAND };
 
-    void initFunction(const char* name, ScriptFunction sf);
-    void addStringArgument();
+    void initFunction(const char* name, DataType returnType, ScriptFunction sf);
+    void addArgument(DataType type);
     void addFunction();
 
-    void start(const char* path);
+    int start(const char* path);
+    void termAll();
+    void callEvent(Event event);
+
+    Pointer toString(Script* sc, const char* s);
 }
 
 #endif

+ 1 - 1
subprojects/lonely-tiger

@@ -1 +1 @@
-Subproject commit 79cfcb9b9ad501e21cdc91c205748d9dabf0413a
+Subproject commit 1694aa362276e223597d590db1c392349b172423