Browse Source

basic integration of snuvi script

Kajetan Johannes Hammerle 3 years ago
parent
commit
eea2d9cef3

+ 2 - 1
meson.build

@@ -13,7 +13,8 @@ src_server = ['server/Main.cpp',
     'server/GameServer.cpp',
     'server/commands/ServerState.cpp',
     'server/commands/CommandManager.cpp',
-    'server/world/WorldGenerator.cpp'
+    'server/world/WorldGenerator.cpp',
+    'server/snuviscript/Snuvi.cpp',
 ]
 
 src_client = ['client/Main.cpp',

+ 5 - 0
resources/scripts/test.snuvi

@@ -0,0 +1,5 @@
+void main() {
+    for(int i = 0; i < 10; i++) {
+        print("HaࠠI Th𐀠eröüäe\n");
+    }
+}

+ 2 - 0
server/Main.cpp

@@ -3,9 +3,11 @@
 #include "network/ENet.h"
 #include "network/Server.h"
 #include "server/GameServer.h"
+#include "server/snuviscript/Snuvi.h"
 #include "utils/Clock.h"
 
 int main() {
+    Snuvi::init();
     ENet enet;
     if(enet.init()) {
         std::cout << "cannot initialize enet\n";

+ 13 - 3
server/commands/CommandManager.cpp

@@ -2,11 +2,12 @@
 
 #include "common/network/Packets.h"
 #include "server/commands/CommandManager.h"
+#include "server/snuviscript/Snuvi.h"
 
 static void commandTest(ServerState&, const CommandArguments& args) {
-    std::cout << "test command" << std::endl;
+    std::cout << "test command\n";
     for(int i = 0; i < args.getLength(); i++) {
-        std::cout << " - " << args[i] << std::endl;
+        std::cout << " - " << args[i] << '\n';
     }
 }
 
@@ -27,10 +28,19 @@ static void commandSay(ServerState& sc, const CommandArguments& args) {
     std::cout << s << '\n';
 }
 
+static void commandScript(ServerState&, const CommandArguments& args) {
+    if(args.getLength() < 2) {
+        std::cout << "/start <script>\n";
+        return;
+    }
+    Snuvi::start(args[1]);
+}
+
 CommandManager::CommandManager() {
     commands.add("test", commandTest);
     commands.add("stop", commandStop);
     commands.add("say", commandSay);
+    commands.add("script", commandScript);
 }
 
 void CommandManager::execute(ServerState& sc, const RawCommand& rawCommand) {
@@ -43,7 +53,7 @@ void CommandManager::execute(ServerState& sc, const RawCommand& rawCommand) {
     CommandName command(args[0]);
     Command* c = commands.search(command);
     if(c == nullptr) {
-        std::cout << "Unknown command: '" << command << "'" << std::endl;
+        std::cout << "Unknown command: '" << command << "'\n";
         return;
     }
     (*c)(sc, args);

+ 112 - 0
server/snuviscript/Snuvi.cpp

@@ -0,0 +1,112 @@
+#include "server/snuviscript/Snuvi.h"
+#include "Compiler.h"
+#include "libraries/Math.h"
+#include "libraries/Time.h"
+#include "tokenizer/Tokenizer.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;
+    if(c > 0xFFFF) {
+        buffer[index++] = 0xF0 | ((c >> 18) & 0x07);
+        buffer[index++] = 0x80 | ((c >> 12) & 0x3F);
+        buffer[index++] = 0x80 | ((c >> 6) & 0x3F);
+        buffer[index++] = 0x80 | (c & 0x3F);
+    } else if(c > 0x7FF) {
+        buffer[index++] = 0xE0 | ((c >> 12) & 0x0F);
+        buffer[index++] = 0x80 | ((c >> 6) & 0x3F);
+        buffer[index++] = 0x80 | (c & 0x3F);
+    } else if(c > 0x7F) {
+        buffer[index++] = 0xC0 | ((c >> 6) & 0x1F);
+        buffer[index++] = 0x80 | (c & 0x3F);
+    } else {
+        buffer[index++] = c;
+    }
+    buffer[index++] = '\0';
+    return buffer;
+}
+
+static void printString(Script* sc) {
+    int length;
+    Pointer p;
+    if(!sPopPointer(sc, &p) || sGetPointerLength(sc, &p, &length)) {
+        return;
+    }
+    for(int i = 0; i < length; i++) {
+        const void* data = sCheckAddress(sc, &p, sizeof(int));
+        if(data != nullptr) {
+            int c;
+            memcpy(&c, data, sizeof(int));
+            printf(unicode(c));
+        }
+        p.offset += sizeof(int);
+    }
+}
+
+static void initPrinter() {
+    Snuvi::initFunction("print", printString);
+    Snuvi::addStringArgument();
+    Snuvi::addFunction();
+}
+
+struct Init {
+    Init() {
+        gfsInit();
+        gstsInit();
+        lTimeRegister();
+        lMathRegister();
+        initPrinter();
+    }
+
+    ~Init() {
+        gfsDelete();
+        gstsDelete();
+    }
+};
+
+void Snuvi::init() {
+    static Init init;
+}
+
+void Snuvi::initFunction(const char* name, ScriptFunction sf) {
+    gfInit(&function, name, dtVoid(), sf);
+}
+
+void Snuvi::addStringArgument() {
+    DataType string = dtConst(dtInt32());
+    dtDereference(&string);
+    gfAddArgument(&function, string);
+}
+
+void Snuvi::addFunction() {
+    gfsAdd(&function);
+}
+
+static void logError(const char* msg, int line) {
+    puts(msg);
+    printf("line: %d\n", line);
+}
+
+void Snuvi::start(const char* path) {
+    StringBuffer<256> s("resources/scripts/");
+    s.append(path).append(".snuvi");
+    if(tTokenize(s)) {
+        logError(tGetError(), tGetLine());
+        return;
+    }
+    ByteCode* code = cCompile();
+    if(code == nullptr) {
+        logError(cGetError(), cGetLine());
+        return;
+    }
+    Script* script = sInit(code);
+    sRun(script);
+    if(script->error[0] != '\0') {
+        logError(script->error, script->line);
+    }
+    sDelete(script);
+}

+ 16 - 0
server/snuviscript/Snuvi.h

@@ -0,0 +1,16 @@
+#ifndef SNUVI_H
+#define SNUVI_H
+
+#include "utils/Functions.h"
+
+namespace Snuvi {
+    void init();
+
+    void initFunction(const char* name, ScriptFunction sf);
+    void addStringArgument();
+    void addFunction();
+
+    void start(const char* path);
+}
+
+#endif

+ 1 - 1
subprojects/lonely-tiger

@@ -1 +1 @@
-Subproject commit 993103cb86db1793b0aac9a19365fa00e7a5c444
+Subproject commit 79cfcb9b9ad501e21cdc91c205748d9dabf0413a