1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Allow ingame console to use clientside commands and print output

This commit is contained in:
Dydzio 2023-01-06 21:01:00 +01:00
parent b1c008179d
commit 622e012fcf
6 changed files with 95 additions and 51 deletions

View File

@ -32,6 +32,7 @@
#include "../lib/ScriptHandler.h" #include "../lib/ScriptHandler.h"
#endif #endif
bool ClientCommandManager::currentCallFromIngameConsole;
void ClientCommandManager::handleGoSolo() void ClientCommandManager::handleGoSolo()
{ {
@ -40,7 +41,7 @@ void ClientCommandManager::handleGoSolo()
boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim); boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim);
if(!CSH->client) if(!CSH->client)
{ {
std::cout << "Game is not in playing state"; printCommandMessage("Game is not in playing state");
return; return;
} }
PlayerColor color; PlayerColor color;
@ -61,7 +62,7 @@ void ClientCommandManager::handleGoSolo()
if(elem.second.human) if(elem.second.human)
{ {
auto AiToGive = CSH->client->aiNameForPlayer(*CSH->client->getPlayerSettings(elem.first), false); auto AiToGive = CSH->client->aiNameForPlayer(*CSH->client->getPlayerSettings(elem.first), false);
logNetwork->info("Player %s will be lead by %s", elem.first, AiToGive); printCommandMessage("Player " + elem.first.getStr() + " will be lead by " + AiToGive, ELogLevel::INFO);
CSH->client->installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), elem.first); CSH->client->installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), elem.first);
} }
} }
@ -76,7 +77,7 @@ void ClientCommandManager::handleControlAi(const std::string &colorName)
boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim); boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim);
if(!CSH->client) if(!CSH->client)
{ {
std::cout << "Game is not in playing state"; printCommandMessage("Game is not in playing state");
return; return;
} }
PlayerColor color; PlayerColor color;
@ -98,18 +99,19 @@ void ClientCommandManager::handleControlAi(const std::string &colorName)
giveTurn(color); giveTurn(color);
} }
#ifndef VCMI_IOS void ClientCommandManager::processCommand(const std::string &message, bool calledFromIngameConsole)
void ClientCommandManager::processCommand(const std::string &message)
{ {
std::istringstream readed; std::istringstream readed;
readed.str(message); readed.str(message);
std::string commandName; std::string commandName;
readed >> commandName; readed >> commandName;
currentCallFromIngameConsole = calledFromIngameConsole;
// Check mantis issue 2292 for details // Check mantis issue 2292 for details
// if(LOCPLINT && LOCPLINT->cingconsole) // if(LOCPLINT && LOCPLINT->cingconsole)
// LOCPLINT->cingconsole->print(message); // LOCPLINT->cingconsole->print(message);
if(message==std::string("die, fool")) if(message==std::string("die, fool"))
{ {
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
@ -130,7 +132,7 @@ void ClientCommandManager::processCommand(const std::string &message)
LOCPLINT->castleInt->activate(); LOCPLINT->castleInt->activate();
break; break;
default: default:
logGlobal->error("Wrong argument specified!"); printCommandMessage("Wrong argument specified!", ELogLevel::ERROR);
} }
} }
else if(commandName == "redraw") else if(commandName == "redraw")
@ -139,14 +141,14 @@ void ClientCommandManager::processCommand(const std::string &message)
} }
else if(commandName == "screen") else if(commandName == "screen")
{ {
std::cout << "Screenbuf points to "; printCommandMessage("Screenbuf points to ");
if(screenBuf == screen) if(screenBuf == screen)
logGlobal->error("screen"); printCommandMessage("screen", ELogLevel::ERROR);
else if(screenBuf == screen2) else if(screenBuf == screen2)
logGlobal->error("screen2"); printCommandMessage("screen2", ELogLevel::ERROR);
else else
logGlobal->error("?!?"); printCommandMessage("?!?", ELogLevel::ERROR);
SDL_SaveBMP(screen, "Screen_c.bmp"); SDL_SaveBMP(screen, "Screen_c.bmp");
SDL_SaveBMP(screen2, "Screen2_c.bmp"); SDL_SaveBMP(screen2, "Screen2_c.bmp");
@ -155,7 +157,7 @@ void ClientCommandManager::processCommand(const std::string &message)
{ {
if(!CSH->client) if(!CSH->client)
{ {
std::cout << "Game is not in playing state"; printCommandMessage("Game is not in playing state");
return; return;
} }
std::string fname; std::string fname;
@ -173,7 +175,7 @@ void ClientCommandManager::processCommand(const std::string &message)
{ {
//TODO: to be replaced with "VLC->generaltexth->dumpAllTexts();" due to https://github.com/vcmi/vcmi/pull/1329 merge: //TODO: to be replaced with "VLC->generaltexth->dumpAllTexts();" due to https://github.com/vcmi/vcmi/pull/1329 merge:
std::cout << "Command accepted.\t"; printCommandMessage("Command accepted.\t");
const boost::filesystem::path outPath = const boost::filesystem::path outPath =
VCMIDirs::get().userExtractedPath(); VCMIDirs::get().userExtractedPath();
@ -201,12 +203,12 @@ void ClientCommandManager::processCommand(const std::string &message)
extractVector(VLC->generaltexth->jktexts, "jkTexts"); extractVector(VLC->generaltexth->jktexts, "jkTexts");
extractVector(VLC->generaltexth->arraytxt, "arrayTexts"); extractVector(VLC->generaltexth->arraytxt, "arrayTexts");
std::cout << "\rExtracting done :)\n"; printCommandMessage("\rExtracting done :)\n");
std::cout << " Extracted files can be found in " << outPath << " directory\n"; printCommandMessage("Extracted files can be found in" + outPath.string() + " directory\n");
} }
else if(message=="get config") else if(message=="get config")
{ {
std::cout << "Command accepted.\t"; printCommandMessage("Command accepted.\t");
const boost::filesystem::path outPath = const boost::filesystem::path outPath =
VCMIDirs::get().userExtractedPath() / "configuration"; VCMIDirs::get().userExtractedPath() / "configuration";
@ -241,13 +243,13 @@ void ClientCommandManager::processCommand(const std::string &message)
} }
} }
std::cout << "\rExtracting done :)\n"; printCommandMessage("\rExtracting done :)\n");
std::cout << " Extracted files can be found in " << outPath << " directory\n"; printCommandMessage("Extracted files can be found in " + outPath.string() + " directory\n");
} }
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED
else if(message=="get scripts") else if(message=="get scripts")
{ {
std::cout << "Command accepted.\t"; printCommandMessage("Command accepted.\t");
const boost::filesystem::path outPath = const boost::filesystem::path outPath =
VCMIDirs::get().userExtractedPath() / "scripts"; VCMIDirs::get().userExtractedPath() / "scripts";
@ -264,13 +266,13 @@ void ClientCommandManager::processCommand(const std::string &message)
boost::filesystem::ofstream file(filePath); boost::filesystem::ofstream file(filePath);
file << script->getSource(); file << script->getSource();
} }
std::cout << "\rExtracting done :)\n"; printCommandMessage("\rExtracting done :)\n");
std::cout << " Extracted files can be found in " << outPath << " directory\n"; printCommandMessage("Extracted files can be found in " + outPath.string() + " directory\n");
} }
#endif #endif
else if(message=="get txt") else if(message=="get txt")
{ {
std::cout << "Command accepted.\t"; printCommandMessage("Command accepted.\t");
const boost::filesystem::path outPath = const boost::filesystem::path outPath =
VCMIDirs::get().userExtractedPath(); VCMIDirs::get().userExtractedPath();
@ -293,8 +295,8 @@ void ClientCommandManager::processCommand(const std::string &message)
file.write((char*)text.first.get(), text.second); file.write((char*)text.first.get(), text.second);
} }
std::cout << "\rExtracting done :)\n"; printCommandMessage("\rExtracting done :)\n");
std::cout << " Extracted files can be found in " << outPath << " directory\n"; printCommandMessage("Extracted files can be found in " + outPath.string() + " directory\n");
} }
else if(commandName == "crash") else if(commandName == "crash")
{ {
@ -305,7 +307,7 @@ void ClientCommandManager::processCommand(const std::string &message)
else if(commandName == "mp" && adventureInt) else if(commandName == "mp" && adventureInt)
{ {
if(const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(adventureInt->selection)) if(const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(adventureInt->selection))
std::cout << h->movement << "; max: " << h->maxMovePoints(true) << "/" << h->maxMovePoints(false) << std::endl; printCommandMessage(std::to_string(h->movement) + "; max: " + std::to_string(h->maxMovePoints(true)) + "/" + std::to_string(h->maxMovePoints(false)) + "\n");
} }
else if(commandName == "bonuses") else if(commandName == "bonuses")
{ {
@ -318,15 +320,15 @@ void ClientCommandManager::processCommand(const std::string &message)
ss << b; ss << b;
return ss.str(); return ss.str();
}; };
std::cout << "Bonuses of " << adventureInt->selection->getObjectName() << std::endl printCommandMessage("Bonuses of " + adventureInt->selection->getObjectName() + "\n");
<< format(adventureInt->selection->getBonusList()) << std::endl; printCommandMessage(format(adventureInt->selection->getBonusList()) + "\n");
std::cout << "\nInherited bonuses:\n"; printCommandMessage("\nInherited bonuses:\n");
TCNodes parents; TCNodes parents;
adventureInt->selection->getParents(parents); adventureInt->selection->getParents(parents);
for(const CBonusSystemNode *parent : parents) for(const CBonusSystemNode *parent : parents)
{ {
std::cout << "\nBonuses from " << typeid(*parent).name() << std::endl << format(*parent->getAllBonuses(Selector::all, Selector::all)) << std::endl; printCommandMessage(std::string("\nBonuses from ") + typeid(*parent).name() + "\n" + format(*parent->getAllBonuses(Selector::all, Selector::all)) + "\n");
} }
} }
else if(commandName == "not dialog") else if(commandName == "not dialog")
@ -341,7 +343,7 @@ void ClientCommandManager::processCommand(const std::string &message)
if(const CIntObject * obj = dynamic_cast<const CIntObject *>(childPtr)) if(const CIntObject * obj = dynamic_cast<const CIntObject *>(childPtr))
printInfoAboutInterfaceObject(obj, 0); printInfoAboutInterfaceObject(obj, 0);
else else
std::cout << typeid(childPtr).name() << std::endl; printCommandMessage(std::string(typeid(childPtr).name()) + "\n");
} }
} }
else if(commandName == "tell") else if(commandName == "tell")
@ -354,7 +356,7 @@ void ClientCommandManager::processCommand(const std::string &message)
for(const CGHeroInstance *h : LOCPLINT->cb->getHeroesInfo()) for(const CGHeroInstance *h : LOCPLINT->cb->getHeroesInfo())
if(h->type->ID.getNum() == id1) if(h->type->ID.getNum() == id1)
if(const CArtifactInstance *a = h->getArt(ArtifactPosition(id2))) if(const CArtifactInstance *a = h->getArt(ArtifactPosition(id2)))
std::cout << a->nodeName(); printCommandMessage(a->nodeName());
} }
} }
else if (commandName == "set") else if (commandName == "set")
@ -369,12 +371,12 @@ void ClientCommandManager::processCommand(const std::string &message)
if (value == "on") if (value == "on")
{ {
config->Bool() = true; config->Bool() = true;
logGlobal->info("Option %s enabled!", what); printCommandMessage("Option " + what + " enabled!", ELogLevel::INFO);
} }
else if (value == "off") else if (value == "off")
{ {
config->Bool() = false; config->Bool() = false;
logGlobal->info("Option %s disabled!", what); printCommandMessage("Option " + what + " disabled!", ELogLevel::INFO);
} }
} }
else if(commandName == "unlock") else if(commandName == "unlock")
@ -408,26 +410,26 @@ void ClientCommandManager::processCommand(const std::string &message)
outFile.write((char*)data.first.get(), data.second); outFile.write((char*)data.first.get(), data.second);
} }
else else
logGlobal->error("File not found!"); printCommandMessage("File not found!", ELogLevel::ERROR);
} }
else if(commandName == "setBattleAI") else if(commandName == "setBattleAI")
{ {
std::string fname; std::string fname;
readed >> fname; readed >> fname;
std::cout << "Will try loading that AI to see if it is correct name...\n"; printCommandMessage("Will try loading that AI to see if it is correct name...\n");
try try
{ {
if(auto ai = CDynLibHandler::getNewBattleAI(fname)) //test that given AI is indeed available... heavy but it is easy to make a typo and break the game if(auto ai = CDynLibHandler::getNewBattleAI(fname)) //test that given AI is indeed available... heavy but it is easy to make a typo and break the game
{ {
Settings neutralAI = settings.write["server"]["neutralAI"]; Settings neutralAI = settings.write["server"]["neutralAI"];
neutralAI->String() = fname; neutralAI->String() = fname;
std::cout << "Setting changed, from now the battle ai will be " << fname << "!\n"; printCommandMessage("Setting changed, from now the battle ai will be " + fname + "!\n");
} }
} }
catch(std::exception &e) catch(std::exception &e)
{ {
logGlobal->warn("Failed opening %s: %s", fname, e.what()); printCommandMessage("Failed opening " + fname + ": " + e.what(), ELogLevel::WARN);
logGlobal->warn("Setting not changed, AI not found or invalid!"); printCommandMessage("Setting not changed, AI not found or invalid!", ELogLevel::WARN);
} }
} }
@ -455,7 +457,6 @@ void ClientCommandManager::processCommand(const std::string &message)
LOCPLINT->cb->sendMessage(message); LOCPLINT->cb->sendMessage(message);
}*/ }*/
} }
#endif
void ClientCommandManager::giveTurn(const PlayerColor &colorIdentifier) void ClientCommandManager::giveTurn(const PlayerColor &colorIdentifier)
{ {
@ -474,7 +475,7 @@ void ClientCommandManager::removeGUI()
GH.listInt.clear(); GH.listInt.clear();
GH.objsToBlit.clear(); GH.objsToBlit.clear();
GH.statusbar = nullptr; GH.statusbar = nullptr;
logGlobal->info("Removed GUI."); printCommandMessage("Removed GUI.", ELogLevel::INFO);
LOCPLINT = nullptr; LOCPLINT = nullptr;
} }
@ -503,8 +504,44 @@ void ClientCommandManager::printInfoAboutInterfaceObject(const CIntObject *obj,
sbuffer << "inactive"; sbuffer << "inactive";
sbuffer << " at " << obj->pos.x <<"x"<< obj->pos.y; sbuffer << " at " << obj->pos.x <<"x"<< obj->pos.y;
sbuffer << " (" << obj->pos.w <<"x"<< obj->pos.h << ")"; sbuffer << " (" << obj->pos.w <<"x"<< obj->pos.h << ")";
logGlobal->info(sbuffer.str()); printCommandMessage(sbuffer.str(), ELogLevel::INFO);
for(const CIntObject *child : obj->children) for(const CIntObject *child : obj->children)
printInfoAboutInterfaceObject(child, level+1); printInfoAboutInterfaceObject(child, level+1);
} }
void ClientCommandManager::printCommandMessage(const std::string &commandMessage, ELogLevel::ELogLevel messageType)
{
switch(messageType)
{
case ELogLevel::NOT_SET:
std::cout << commandMessage;
break;
case ELogLevel::TRACE:
logGlobal->trace(commandMessage);
break;
case ELogLevel::DEBUG:
logGlobal->debug(commandMessage);
break;
case ELogLevel::INFO:
logGlobal->info(commandMessage);
break;
case ELogLevel::WARN:
logGlobal->warn(commandMessage);
break;
case ELogLevel::ERROR:
logGlobal->error(commandMessage);
break;
default:
std::cout << commandMessage;
break;
}
if(currentCallFromIngameConsole)
{
if(LOCPLINT && LOCPLINT->cingconsole)
{
LOCPLINT->cingconsole->print(commandMessage);
}
}
}

View File

@ -15,13 +15,16 @@ class CIntObject;
class ClientCommandManager class ClientCommandManager
{ {
static bool currentCallFromIngameConsole;
static void giveTurn(const PlayerColor &color); static void giveTurn(const PlayerColor &color);
static void removeGUI(); static void removeGUI();
static void printInfoAboutInterfaceObject(const CIntObject *obj, int level); static void printInfoAboutInterfaceObject(const CIntObject *obj, int level);
public: static void printCommandMessage(const std::string &commandMessage, ELogLevel::ELogLevel messageType = ELogLevel::NOT_SET);
#ifndef VCMI_IOS
static void processCommand(const std::string &message);
#endif
static void handleGoSolo(); static void handleGoSolo();
static void handleControlAi(const std::string &colorName); static void handleControlAi(const std::string &colorName);
public:
ClientCommandManager() = delete;
static void processCommand(const std::string &message, bool calledFromIngameConsole);
}; };

View File

@ -48,6 +48,7 @@
#include "../../lib/mapping/CMap.h" #include "../../lib/mapping/CMap.h"
#include "../../lib/NetPacksBase.h" #include "../../lib/NetPacksBase.h"
#include "../../lib/StringConstants.h" #include "../../lib/StringConstants.h"
#include "ClientCommandManager.h"
CList::CListItem::CListItem(CList * Parent) CList::CListItem::CListItem(CList * Parent)
: CIntObject(LCLICK | RCLICK | HOVER), : CIntObject(LCLICK | RCLICK | HOVER),
@ -1144,15 +1145,18 @@ void CInGameConsole::startEnteringText()
GH.statusbar->setEnteredText(enteredText); GH.statusbar->setEnteredText(enteredText);
} }
void CInGameConsole::endEnteringText(bool printEnteredText) void CInGameConsole::endEnteringText(bool processEnteredText)
{ {
captureAllKeys = false; captureAllKeys = false;
prevEntDisp = -1; prevEntDisp = -1;
if(printEnteredText) if(processEnteredText)
{ {
std::string txt = enteredText.substr(0, enteredText.size()-1); std::string txt = enteredText.substr(0, enteredText.size()-1);
LOCPLINT->cb->sendMessage(txt, LOCPLINT->getSelection()); LOCPLINT->cb->sendMessage(txt, LOCPLINT->getSelection());
previouslyEntered.push_back(txt); previouslyEntered.push_back(txt);
boost::thread clientCommandThread(ClientCommandManager::processCommand, txt, true);
clientCommandThread.join();
} }
enteredText.clear(); enteredText.clear();

View File

@ -424,7 +424,7 @@ public:
void textEdited(const SDL_TextEditingEvent & event) override; void textEdited(const SDL_TextEditingEvent & event) override;
void startEnteringText(); void startEnteringText();
void endEnteringText(bool printEnteredText); void endEnteringText(bool processEnteredText);
void refreshEnteredText(); void refreshEnteredText();
CInGameConsole(); CInGameConsole();

View File

@ -230,7 +230,7 @@ int CConsoleHandler::run()
{ {
if ( getline(std::cin, buffer).good() ) if ( getline(std::cin, buffer).good() )
if ( cb && *cb ) if ( cb && *cb )
(*cb)(buffer); (*cb)(buffer, false);
} }
else else
boost::this_thread::sleep(boost::posix_time::millisec(100)); boost::this_thread::sleep(boost::posix_time::millisec(100));
@ -239,7 +239,7 @@ int CConsoleHandler::run()
#else #else
std::getline(std::cin, buffer); std::getline(std::cin, buffer);
if ( cb && *cb ) if ( cb && *cb )
(*cb)(buffer); (*cb)(buffer, false);
#endif #endif
} }
return -1; return -1;
@ -263,7 +263,7 @@ CConsoleHandler::CConsoleHandler() : thread(nullptr)
#else #else
defColor = "\x1b[0m"; defColor = "\x1b[0m";
#endif #endif
cb = new std::function<void(const std::string &)>; cb = new std::function<void(const std::string &, bool)>;
} }
CConsoleHandler::~CConsoleHandler() CConsoleHandler::~CConsoleHandler()
{ {

View File

@ -76,7 +76,7 @@ public:
#endif #endif
} }
std::function<void(const std::string &)> *cb; //function to be called when message is received std::function<void(const std::string &, bool)> *cb; //function to be called when message is received
private: private:
int run(); int run();