Browse Source

console commands can nw be executed and have autocompletion

Kolja Strohm 2 months ago
parent
commit
f6d885102e

+ 5 - 2
FactoryCraft/BlockInfoCommand.cpp

@@ -24,8 +24,8 @@ BlockInfoCommand::BlockInfoCommand()
         }));
 }
 
-void BlockInfoCommand::execute(
-    Framework::RCArray<Framework::Text> params, Entity* zActor) const
+bool BlockInfoCommand::execute(
+    Framework::RCArray<Framework::Text>& params, Entity* zActor) const
 {
     int x = (int)*params.z(0);
     int y = (int)*params.z(1);
@@ -33,6 +33,7 @@ void BlockInfoCommand::execute(
     int dimension = (int)*params.z(3);
     Framework::Vec3<int> location = {x, y, z};
     Framework::Text result = "";
+    bool ok = 1;
     if (Game::INSTANCE->zDimension(dimension))
     {
         auto block = Game::INSTANCE->zBlockAt(location, dimension);
@@ -139,6 +140,7 @@ void BlockInfoCommand::execute(
     else
     {
         result += "Given dimension is not loaded";
+        ok = 0;
     }
     if (zActor)
     {
@@ -149,4 +151,5 @@ void BlockInfoCommand::execute(
     {
         Framework::Logging::info() << result;
     }
+    return ok;
 }

+ 1 - 1
FactoryCraft/BlockInfoCommand.h

@@ -7,6 +7,6 @@ class BlockInfoCommand : public ChatCommand
 public:
     BlockInfoCommand();
 
-    void execute(Framework::RCArray<Framework::Text> params,
+    bool execute(Framework::RCArray<Framework::Text>& params,
         Entity* zActor) const override;
 };

+ 66 - 7
FactoryCraft/ChatCommand.cpp

@@ -1,12 +1,13 @@
 #include "ChatCommand.h"
 
+#include <AsynchronCall.h>
+
 #include "Game.h"
 #include "Player.h"
 
 ChatCommand::ChatCommand(
     Framework::Text name, Framework::Text description, int securityLevel)
-    : Framework::ReferenceCounter(),
-      name(name),
+    : Framework::ConsoleCommand(name),
       description(description),
       securityLevel(securityLevel)
 {}
@@ -16,20 +17,55 @@ void ChatCommand::addParam(ChatCommandParameter* param)
     params.add(param);
 }
 
-const Framework::RCArray<ChatCommandParameter>& ChatCommand::getParams() const
+bool ChatCommand::execute(Framework::RCArray<Framework::Text>& params) const
 {
-    return params;
+    return execute(params, 0);
 }
 
-Framework::Text ChatCommand::getName() const
+void ChatCommand::addAutocompletePossibilities(
+    const Framework::RCArray<Framework::Text>& args,
+    bool appendToLast,
+    Framework::RCArray<Framework::Text>& possibilities) const
 {
-    return name;
+    int index
+        = appendToLast ? args.getEintragAnzahl() - 1 : args.getEintragAnzahl();
+    if (index < 0 || index >= params.getEintragAnzahl()) return;
+    for (Framework::Text* possibility : params.z(index)->getAutocompleteValues(
+             appendToLast ? *args.z(args.getEintragAnzahl() - 1)
+                          : Framework::Text("")))
+    {
+        possibilities.add(
+            dynamic_cast<Framework::Text*>(possibility->getThis()));
+    }
+    if (possibilities.getEintragAnzahl() == 0
+        || (possibilities.getEintragAnzahl() == 1 && appendToLast
+            && possibilities.z(0)->istGleich(
+                args.get(args.getEintragAnzahl() - 1))))
+    {
+        Framework::Text help = getHelp();
+        while (help.hat("\n"))
+        {
+            Framework::Text* line = help.getTeilText(0, help.positionVon("\n"));
+            Framework::Logging::info() << line->getText();
+            help.remove(0, line->getLength() + 1);
+            line->release();
+        }
+        if (help.getLength() > 0)
+        {
+            Framework::Logging::info() << help;
+        }
+    }
+}
+
+const Framework::RCArray<ChatCommandParameter>& ChatCommand::getParams() const
+{
+    return params;
 }
 
 Framework::Text ChatCommand::getHelp() const
 {
     Framework::Text result = "/";
-    result += name;
+    result += getName();
 
     for (ChatCommandParameter* param : params)
     {
@@ -95,6 +131,12 @@ bool ChatCommandParameter::isOptional() const
     return optional;
 }
 
+Framework::RCArray<Framework::Text> ChatCommandParameter::getAutocompleteValues(
+    const Framework::Text& current) const
+{
+    return Framework::RCArray<Framework::Text>();
+}
+
 PlayerNameParameter::PlayerNameParameter()
     : ChatCommandParameter(
         "player", "The name of the player (has to be online)", 0)
@@ -112,6 +154,23 @@ Framework::Text PlayerNameParameter::getDefaultValue(Entity* zActor) const
     return "";
 }
 
+Framework::RCArray<Framework::Text> PlayerNameParameter::getAutocompleteValues(
+    const Framework::Text& current) const
+{
+    Framework::RCArray<Framework::Text> result;
+    Game::INSTANCE->listPlayerNames(result);
+    for (auto iterator = result.begin(); iterator;)
+    {
+        if (iterator->hatAt(0, current))
+        {
+            iterator.remove();
+        }
+        else
+            ++iterator;
+    }
+    return result;
+}
+
 IntegerParameter::IntegerParameter(Framework::Text name,
     Framework::Text description,
     bool optional,

+ 17 - 8
FactoryCraft/ChatCommand.h

@@ -7,26 +7,31 @@
 
 class ChatCommandParameter;
 
-class ChatCommand : public virtual Framework::ReferenceCounter
+class ChatCommand : public Framework::ConsoleCommand
 {
 private:
-    Framework::Text name;
     Framework::Text description;
     int securityLevel;
     Framework::RCArray<ChatCommandParameter> params;
 
-protected:
-    void addParam(ChatCommandParameter* param);
-
 public:
     ChatCommand(
         Framework::Text name, Framework::Text description, int securityLevel);
 
-    virtual void execute(
-        Framework::RCArray<Framework::Text> params, Entity* zActor) const = 0;
+protected:
+    void addParam(ChatCommandParameter* param);
+
+public:
+    virtual bool execute(
+        Framework::RCArray<Framework::Text>& params, Entity* zActor) const
+        = 0;
+    bool execute(Framework::RCArray<Framework::Text>& params) const override;
+    void addAutocompletePossibilities(
+        const Framework::RCArray<Framework::Text>& args,
+        bool appendToLast,
+        Framework::RCArray<Framework::Text>& possibilities) const override;
 
     const Framework::RCArray<ChatCommandParameter>& getParams() const;
-    Framework::Text getName() const;
     Framework::Text getHelp() const;
     virtual int getSecurityLevel(
         Framework::RCArray<Framework::Text> params) const;
@@ -48,6 +53,8 @@ public:
     Framework::Text getName() const;
     Framework::Text getDescription() const;
     bool isOptional() const;
+    virtual Framework::RCArray<Framework::Text> getAutocompleteValues(
+        const Framework::Text& current) const;
 };
 
 class PlayerNameParameter : public ChatCommandParameter
@@ -57,6 +64,8 @@ public:
 
     bool isLegalValue(Framework::Text value) const override;
     Framework::Text getDefaultValue(Entity* zActor) const override;
+    Framework::RCArray<Framework::Text> getAutocompleteValues(
+        const Framework::Text& current) const override;
 };
 
 class IntegerParameter : public ChatCommandParameter

+ 6 - 0
FactoryCraft/ChatCommandExecutor.cpp

@@ -12,6 +12,12 @@ ChatCommandExecutor::ChatCommandExecutor()
     knownCommands.add(new SaveCommand());
     knownCommands.add(new CrantCommand());
     knownCommands.add(new BlockInfoCommand());
+    // Add more commands here
+    for (ChatCommand* command : knownCommands)
+    {
+        Game::INSTANCE->consoleInput->addPossibleCommand(
+            dynamic_cast<Framework::ConsoleCommand*>(command->getThis()));
+    }
 }
 
 bool ChatCommandExecutor::execute(Framework::Text line, Entity* zActor)

+ 8 - 0
FactoryCraft/Game.cpp

@@ -1337,6 +1337,14 @@ Player* Game::zPlayerByName(const char* name) const
     return 0;
 }
 
+void Game::listPlayerNames(Framework::RCArray<Framework::Text>& names)
+{
+    for (GameClient* client : *clients)
+    {
+        names.add(new Framework::Text(client->zEntity()->getName()));
+    }
+}
+
 TypeRegistry* Game::zTypeRegistry() const
 {
     return typeRegistry;

+ 1 - 0
FactoryCraft/Game.h

@@ -171,6 +171,7 @@ public:
     TickOrganizer* zTickOrganizer() const;
     Chat* zChat() const;
     Player* zPlayerByName(const char* name) const;
+    void listPlayerNames(Framework::RCArray<Framework::Text>& names);
     TypeRegistry* zTypeRegistry() const;
     int getPlayerId(const char* name) const;
     QuestManager* zQuestManager() const;

+ 4 - 2
FactoryCraft/GrantCommand.cpp

@@ -17,8 +17,8 @@ CrantCommand::CrantCommand()
         }));
 }
 
-void CrantCommand::execute(
-    Framework::RCArray<Framework::Text> params, Entity* zActor) const
+bool CrantCommand::execute(
+    Framework::RCArray<Framework::Text>& params, Entity* zActor) const
 {
     int securityLevel = (int)*params.z(1);
     Entity* zTarget = Game::INSTANCE->zPlayerByName(*params.z(0));
@@ -29,7 +29,9 @@ void CrantCommand::execute(
         message.append() << *params.z(0) << " is now set to " << securityLevel;
         Game::INSTANCE->zChat()->sendMessageTo(
             message, zActor, Chat::CHANNEL_INFO);
+        return true;
     }
+    return false;
 }
 
 int CrantCommand::getSecurityLevel(

+ 1 - 1
FactoryCraft/GrantCommand.h

@@ -6,7 +6,7 @@ class CrantCommand : public ChatCommand
 {
 public:
     CrantCommand();
-    void execute(Framework::RCArray<Framework::Text> params,
+    bool execute(Framework::RCArray<Framework::Text>& params,
         Entity* zActor) const override;
     int getSecurityLevel(
         Framework::RCArray<Framework::Text> params) const override;

+ 3 - 2
FactoryCraft/SaveCommand.cpp

@@ -7,10 +7,11 @@ SaveCommand::SaveCommand()
     : ChatCommand("save", "Saves the game", 0)
 {}
 
-void SaveCommand::execute(
-    Framework::RCArray<Framework::Text> params, Entity* zActor) const
+bool SaveCommand::execute(
+    Framework::RCArray<Framework::Text>& params, Entity* zActor) const
 {
     Game::INSTANCE->save();
     Game::INSTANCE->zChat()->broadcastMessage(
         "The game was saved.", Chat::CHANNEL_INFO);
+    return true;
 }

+ 1 - 1
FactoryCraft/SaveCommand.h

@@ -6,6 +6,6 @@ class SaveCommand : public ChatCommand
 {
 public:
     SaveCommand();
-    void execute(Framework::RCArray<Framework::Text> params,
+    bool execute(Framework::RCArray<Framework::Text>& params,
         Entity* zActor) const override;
 };