|
@@ -42,7 +42,34 @@
|
|
|
|
|
|
#include <SDL_surface.h>
|
|
#include <SDL_surface.h>
|
|
|
|
|
|
-void ClientCommandManager::handleGoSolo()
|
|
|
|
|
|
+void ClientCommandManager::handleQuitCommand()
|
|
|
|
+{
|
|
|
|
+ exit(EXIT_SUCCESS);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::handleSaveCommand(std::istringstream & singleWordBuffer)
|
|
|
|
+{
|
|
|
|
+ if(!CSH->client)
|
|
|
|
+ {
|
|
|
|
+ printCommandMessage("Game is not in playing state");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ std::string saveFilename;
|
|
|
|
+ singleWordBuffer >> saveFilename;
|
|
|
|
+ CSH->client->save(saveFilename);
|
|
|
|
+ printCommandMessage("Game saved as: " + saveFilename);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::handleLoadCommand(std::istringstream& singleWordBuffer)
|
|
|
|
+{
|
|
|
|
+ // TODO: this code should end the running game and manage to call startGame instead
|
|
|
|
+ //std::string fname;
|
|
|
|
+ //singleWordBuffer >> fname;
|
|
|
|
+ //CSH->client->loadGame(fname);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::handleGoSoloCommand()
|
|
{
|
|
{
|
|
Settings session = settings.write["session"];
|
|
Settings session = settings.write["session"];
|
|
|
|
|
|
@@ -80,21 +107,33 @@ void ClientCommandManager::handleGoSolo()
|
|
session["aiSolo"].Bool() = !session["aiSolo"].Bool();
|
|
session["aiSolo"].Bool() = !session["aiSolo"].Bool();
|
|
}
|
|
}
|
|
|
|
|
|
-void ClientCommandManager::handleControlAi(const std::string &colorName)
|
|
|
|
|
|
+void ClientCommandManager::handleAutoskipCommand()
|
|
|
|
+{
|
|
|
|
+ Settings session = settings.write["session"];
|
|
|
|
+ session["autoSkip"].Bool() = !session["autoSkip"].Bool();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::handleControlaiCommand(std::istringstream& singleWordBuffer)
|
|
{
|
|
{
|
|
|
|
+ std::string colorName;
|
|
|
|
+ singleWordBuffer >> colorName;
|
|
|
|
+ boost::to_lower(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)
|
|
{
|
|
{
|
|
printCommandMessage("Game is not in playing state");
|
|
printCommandMessage("Game is not in playing state");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+
|
|
PlayerColor color;
|
|
PlayerColor color;
|
|
if(LOCPLINT)
|
|
if(LOCPLINT)
|
|
color = LOCPLINT->playerID;
|
|
color = LOCPLINT->playerID;
|
|
|
|
+
|
|
for(auto & elem : CSH->client->gameState()->players)
|
|
for(auto & elem : CSH->client->gameState()->players)
|
|
{
|
|
{
|
|
- if(elem.second.human || (colorName.length() &&
|
|
|
|
- elem.first.getNum() != vstd::find_pos(GameConstants::PLAYER_COLOR_NAMES, colorName)))
|
|
|
|
|
|
+ if(elem.second.human ||
|
|
|
|
+ (colorName.length() && elem.first.getNum() != vstd::find_pos(GameConstants::PLAYER_COLOR_NAMES, colorName)))
|
|
{
|
|
{
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
@@ -102,386 +141,319 @@ void ClientCommandManager::handleControlAi(const std::string &colorName)
|
|
CSH->client->removeGUI();
|
|
CSH->client->removeGUI();
|
|
CSH->client->installNewPlayerInterface(std::make_shared<CPlayerInterface>(elem.first), elem.first);
|
|
CSH->client->installNewPlayerInterface(std::make_shared<CPlayerInterface>(elem.first), elem.first);
|
|
}
|
|
}
|
|
|
|
+
|
|
GH.totalRedraw();
|
|
GH.totalRedraw();
|
|
if(color != PlayerColor::NEUTRAL)
|
|
if(color != PlayerColor::NEUTRAL)
|
|
giveTurn(color);
|
|
giveTurn(color);
|
|
}
|
|
}
|
|
|
|
|
|
-void ClientCommandManager::processCommand(const std::string &message, bool calledFromIngameConsole)
|
|
|
|
|
|
+void ClientCommandManager::handleSetBattleAICommand(std::istringstream& singleWordBuffer)
|
|
{
|
|
{
|
|
- std::istringstream singleWordBuffer;
|
|
|
|
- singleWordBuffer.str(message);
|
|
|
|
- std::string commandName;
|
|
|
|
- singleWordBuffer >> commandName;
|
|
|
|
- currentCallFromIngameConsole = calledFromIngameConsole;
|
|
|
|
|
|
+ std::string aiName;
|
|
|
|
+ singleWordBuffer >> aiName;
|
|
|
|
|
|
- if(message==std::string("die, fool"))
|
|
|
|
|
|
+ printCommandMessage("Will try loading that AI to see if it is correct name...\n");
|
|
|
|
+ try
|
|
{
|
|
{
|
|
- exit(EXIT_SUCCESS);
|
|
|
|
|
|
+ if(auto ai = CDynLibHandler::getNewBattleAI(aiName)) //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"];
|
|
|
|
+ neutralAI->String() = aiName;
|
|
|
|
+ printCommandMessage("Setting changed, from now the battle ai will be " + aiName + "!\n");
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- else if(commandName == "redraw")
|
|
|
|
|
|
+ catch(std::exception &e)
|
|
{
|
|
{
|
|
- GH.totalRedraw();
|
|
|
|
|
|
+ printCommandMessage("Failed opening " + aiName + ": " + e.what(), ELogLevel::WARN);
|
|
|
|
+ printCommandMessage("Setting not changed, AI not found or invalid!", ELogLevel::WARN);
|
|
}
|
|
}
|
|
- else if(commandName == "screen")
|
|
|
|
- {
|
|
|
|
- printCommandMessage("Screenbuf points to ");
|
|
|
|
|
|
+}
|
|
|
|
|
|
- if(screenBuf == screen)
|
|
|
|
- printCommandMessage("screen", ELogLevel::ERROR);
|
|
|
|
- else if(screenBuf == screen2)
|
|
|
|
- printCommandMessage("screen2", ELogLevel::ERROR);
|
|
|
|
- else
|
|
|
|
- printCommandMessage("?!?", ELogLevel::ERROR);
|
|
|
|
|
|
+void ClientCommandManager::handleRedrawCommand()
|
|
|
|
+{
|
|
|
|
+ GH.totalRedraw();
|
|
|
|
+}
|
|
|
|
|
|
- SDL_SaveBMP(screen, "Screen_c.bmp");
|
|
|
|
- SDL_SaveBMP(screen2, "Screen2_c.bmp");
|
|
|
|
- }
|
|
|
|
- else if(commandName == "save")
|
|
|
|
|
|
+void ClientCommandManager::handleScreenCommand()
|
|
|
|
+{
|
|
|
|
+ printCommandMessage("Screenbuf points to ");
|
|
|
|
+
|
|
|
|
+ if(screenBuf == screen)
|
|
|
|
+ printCommandMessage("screen", ELogLevel::ERROR);
|
|
|
|
+ else if(screenBuf == screen2)
|
|
|
|
+ printCommandMessage("screen2", ELogLevel::ERROR);
|
|
|
|
+ else
|
|
|
|
+ printCommandMessage("?!?", ELogLevel::ERROR);
|
|
|
|
+
|
|
|
|
+ SDL_SaveBMP(screen, "Screen_c.bmp");
|
|
|
|
+ SDL_SaveBMP(screen2, "Screen2_c.bmp");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::handleNotDialogCommand()
|
|
|
|
+{
|
|
|
|
+ LOCPLINT->showingDialog->setn(false);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::handleGuiCommand()
|
|
|
|
+{
|
|
|
|
+ for(const auto & child : GH.listInt)
|
|
{
|
|
{
|
|
- if(!CSH->client)
|
|
|
|
- {
|
|
|
|
- printCommandMessage("Game is not in playing state");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- std::string fname;
|
|
|
|
- singleWordBuffer >> fname;
|
|
|
|
- CSH->client->save(fname);
|
|
|
|
|
|
+ const auto childPtr = child.get();
|
|
|
|
+ if(const CIntObject * obj = dynamic_cast<const CIntObject*>(childPtr))
|
|
|
|
+ printInfoAboutInterfaceObject(obj, 0);
|
|
|
|
+ else
|
|
|
|
+ printCommandMessage(std::string(typeid(childPtr).name()) + "\n");
|
|
}
|
|
}
|
|
-// else if(commandName=="load")
|
|
|
|
-// {
|
|
|
|
-// // TODO: this code should end the running game and manage to call startGame instead
|
|
|
|
-// std::string fname;
|
|
|
|
-// singleWordBuffer >> fname;
|
|
|
|
-// CSH->client->loadGame(fname);
|
|
|
|
-// }
|
|
|
|
- else if(message=="convert txt")
|
|
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::handleConvertTextCommand()
|
|
|
|
+{
|
|
|
|
+ logGlobal->info("Searching for available maps");
|
|
|
|
+ std::unordered_set<ResourceID> mapList = CResourceHandler::get()->getFilteredFiles([&](const ResourceID & ident)
|
|
{
|
|
{
|
|
- logGlobal->info("Searching for available maps");
|
|
|
|
- std::unordered_set<ResourceID> mapList = CResourceHandler::get()->getFilteredFiles([&](const ResourceID & ident)
|
|
|
|
- {
|
|
|
|
- return ident.getType() == EResType::MAP;
|
|
|
|
- });
|
|
|
|
|
|
+ return ident.getType() == EResType::MAP;
|
|
|
|
+ });
|
|
|
|
|
|
- std::unordered_set<ResourceID> campaignList = CResourceHandler::get()->getFilteredFiles([&](const ResourceID & ident)
|
|
|
|
- {
|
|
|
|
- return ident.getType() == EResType::CAMPAIGN;
|
|
|
|
- });
|
|
|
|
|
|
+ std::unordered_set<ResourceID> campaignList = CResourceHandler::get()->getFilteredFiles([&](const ResourceID & ident)
|
|
|
|
+ {
|
|
|
|
+ return ident.getType() == EResType::CAMPAIGN;
|
|
|
|
+ });
|
|
|
|
|
|
- CMapService mapService;
|
|
|
|
|
|
+ CMapService mapService;
|
|
|
|
|
|
- logGlobal->info("Loading maps for export");
|
|
|
|
- for (auto const & mapName : mapList)
|
|
|
|
|
|
+ logGlobal->info("Loading maps for export");
|
|
|
|
+ for (auto const & mapName : mapList)
|
|
|
|
+ {
|
|
|
|
+ try
|
|
{
|
|
{
|
|
- try
|
|
|
|
- {
|
|
|
|
- // load and drop loaded map - we only need loader to run over all maps
|
|
|
|
- mapService.loadMap(mapName);
|
|
|
|
- }
|
|
|
|
- catch(std::exception & e)
|
|
|
|
- {
|
|
|
|
- logGlobal->error("Map %s is invalid. Message: %s", mapName.getName(), e.what());
|
|
|
|
- }
|
|
|
|
|
|
+ // load and drop loaded map - we only need loader to run over all maps
|
|
|
|
+ mapService.loadMap(mapName);
|
|
}
|
|
}
|
|
-
|
|
|
|
- logGlobal->info("Loading campaigns for export");
|
|
|
|
- for (auto const & campaignName : campaignList)
|
|
|
|
|
|
+ catch(std::exception & e)
|
|
{
|
|
{
|
|
- CCampaignState state(CCampaignHandler::getCampaign(campaignName.getName()));
|
|
|
|
- for (auto const & part : state.camp->mapPieces)
|
|
|
|
- delete state.getMap(part.first);
|
|
|
|
|
|
+ logGlobal->error("Map %s is invalid. Message: %s", mapName.getName(), e.what());
|
|
}
|
|
}
|
|
-
|
|
|
|
- VLC->generaltexth->dumpAllTexts();
|
|
|
|
}
|
|
}
|
|
- else if(message=="get config")
|
|
|
|
|
|
+
|
|
|
|
+ logGlobal->info("Loading campaigns for export");
|
|
|
|
+ for (auto const & campaignName : campaignList)
|
|
{
|
|
{
|
|
- printCommandMessage("Command accepted.\t");
|
|
|
|
|
|
+ CCampaignState state(CCampaignHandler::getCampaign(campaignName.getName()));
|
|
|
|
+ for (auto const & part : state.camp->mapPieces)
|
|
|
|
+ delete state.getMap(part.first);
|
|
|
|
+ }
|
|
|
|
|
|
- const boost::filesystem::path outPath =
|
|
|
|
- VCMIDirs::get().userExtractedPath() / "configuration";
|
|
|
|
|
|
+ VLC->generaltexth->dumpAllTexts();
|
|
|
|
+}
|
|
|
|
|
|
- boost::filesystem::create_directories(outPath);
|
|
|
|
|
|
+void ClientCommandManager::handleGetConfigCommand()
|
|
|
|
+{
|
|
|
|
+ printCommandMessage("Command accepted.\t");
|
|
|
|
|
|
- const std::vector<std::string> contentNames = {"heroClasses", "artifacts", "creatures", "factions", "objects", "heroes", "spells", "skills"};
|
|
|
|
|
|
+ const boost::filesystem::path outPath = VCMIDirs::get().userExtractedPath() / "configuration";
|
|
|
|
|
|
- for(auto contentName : contentNames)
|
|
|
|
- {
|
|
|
|
- auto & content = (*VLC->modh->content)[contentName];
|
|
|
|
|
|
+ boost::filesystem::create_directories(outPath);
|
|
|
|
|
|
- auto contentOutPath = outPath / contentName;
|
|
|
|
- boost::filesystem::create_directories(contentOutPath);
|
|
|
|
|
|
+ const std::vector<std::string> contentNames = { "heroClasses", "artifacts", "creatures", "factions", "objects", "heroes", "spells", "skills" };
|
|
|
|
|
|
- for(auto & iter : content.modData)
|
|
|
|
- {
|
|
|
|
- const JsonNode & modData = iter.second.modData;
|
|
|
|
|
|
+ for(auto contentName : contentNames)
|
|
|
|
+ {
|
|
|
|
+ auto& content = (*VLC->modh->content)[contentName];
|
|
|
|
|
|
- for(auto & nameAndObject : modData.Struct())
|
|
|
|
- {
|
|
|
|
- const JsonNode & object = nameAndObject.second;
|
|
|
|
|
|
+ auto contentOutPath = outPath / contentName;
|
|
|
|
+ boost::filesystem::create_directories(contentOutPath);
|
|
|
|
|
|
- std::string name = CModHandler::makeFullIdentifier(object.meta, contentName, nameAndObject.first);
|
|
|
|
|
|
+ for(auto& iter : content.modData)
|
|
|
|
+ {
|
|
|
|
+ const JsonNode& modData = iter.second.modData;
|
|
|
|
+
|
|
|
|
+ for(auto& nameAndObject : modData.Struct())
|
|
|
|
+ {
|
|
|
|
+ const JsonNode& object = nameAndObject.second;
|
|
|
|
|
|
- boost::algorithm::replace_all(name,":","_");
|
|
|
|
|
|
+ std::string name = CModHandler::makeFullIdentifier(object.meta, contentName, nameAndObject.first);
|
|
|
|
|
|
- const boost::filesystem::path filePath = contentOutPath / (name + ".json");
|
|
|
|
- boost::filesystem::ofstream file(filePath);
|
|
|
|
- file << object.toJson();
|
|
|
|
- }
|
|
|
|
|
|
+ boost::algorithm::replace_all(name, ":", "_");
|
|
|
|
+
|
|
|
|
+ const boost::filesystem::path filePath = contentOutPath / (name + ".json");
|
|
|
|
+ boost::filesystem::ofstream file(filePath);
|
|
|
|
+ file << object.toJson();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- printCommandMessage("\rExtracting done :)\n");
|
|
|
|
- printCommandMessage("Extracted files can be found in " + outPath.string() + " directory\n");
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ printCommandMessage("\rExtracting done :)\n");
|
|
|
|
+ printCommandMessage("Extracted files can be found in " + outPath.string() + " directory\n");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::handleGetScriptsCommand()
|
|
|
|
+{
|
|
#if SCRIPTING_ENABLED
|
|
#if SCRIPTING_ENABLED
|
|
- else if(message=="get scripts")
|
|
|
|
- {
|
|
|
|
- printCommandMessage("Command accepted.\t");
|
|
|
|
|
|
+ printCommandMessage("Command accepted.\t");
|
|
|
|
|
|
- const boost::filesystem::path outPath =
|
|
|
|
- VCMIDirs::get().userExtractedPath() / "scripts";
|
|
|
|
|
|
+ const boost::filesystem::path outPath = VCMIDirs::get().userExtractedPath() / "scripts";
|
|
|
|
|
|
- boost::filesystem::create_directories(outPath);
|
|
|
|
|
|
+ boost::filesystem::create_directories(outPath);
|
|
|
|
|
|
- for(auto & kv : VLC->scriptHandler->objects)
|
|
|
|
- {
|
|
|
|
- std::string name = kv.first;
|
|
|
|
- boost::algorithm::replace_all(name,":","_");
|
|
|
|
|
|
+ for(auto & kv : VLC->scriptHandler->objects)
|
|
|
|
+ {
|
|
|
|
+ std::string name = kv.first;
|
|
|
|
+ boost::algorithm::replace_all(name,":","_");
|
|
|
|
|
|
- const scripting::ScriptImpl * script = kv.second.get();
|
|
|
|
- boost::filesystem::path filePath = outPath / (name + ".lua");
|
|
|
|
- boost::filesystem::ofstream file(filePath);
|
|
|
|
- file << script->getSource();
|
|
|
|
- }
|
|
|
|
- printCommandMessage("\rExtracting done :)\n");
|
|
|
|
- printCommandMessage("Extracted files can be found in " + outPath.string() + " directory\n");
|
|
|
|
|
|
+ const scripting::ScriptImpl * script = kv.second.get();
|
|
|
|
+ boost::filesystem::path filePath = outPath / (name + ".lua");
|
|
|
|
+ boost::filesystem::ofstream file(filePath);
|
|
|
|
+ file << script->getSource();
|
|
}
|
|
}
|
|
|
|
+ printCommandMessage("\rExtracting done :)\n");
|
|
|
|
+ printCommandMessage("Extracted files can be found in " + outPath.string() + " directory\n");
|
|
#endif
|
|
#endif
|
|
- else if(message=="get txt")
|
|
|
|
- {
|
|
|
|
- printCommandMessage("Command accepted.\t");
|
|
|
|
|
|
+}
|
|
|
|
|
|
- const boost::filesystem::path outPath =
|
|
|
|
- VCMIDirs::get().userExtractedPath();
|
|
|
|
|
|
+void ClientCommandManager::handleGetTextCommand()
|
|
|
|
+{
|
|
|
|
+ printCommandMessage("Command accepted.\t");
|
|
|
|
|
|
- auto list =
|
|
|
|
- CResourceHandler::get()->getFilteredFiles([](const ResourceID & ident)
|
|
|
|
- {
|
|
|
|
- return ident.getType() == EResType::TEXT && boost::algorithm::starts_with(ident.getName(), "DATA/");
|
|
|
|
- });
|
|
|
|
|
|
+ const boost::filesystem::path outPath =
|
|
|
|
+ VCMIDirs::get().userExtractedPath();
|
|
|
|
|
|
- for (auto & filename : list)
|
|
|
|
- {
|
|
|
|
- const boost::filesystem::path filePath = outPath / (filename.getName() + ".TXT");
|
|
|
|
|
|
+ auto list =
|
|
|
|
+ CResourceHandler::get()->getFilteredFiles([](const ResourceID & ident)
|
|
|
|
+ {
|
|
|
|
+ return ident.getType() == EResType::TEXT && boost::algorithm::starts_with(ident.getName(), "DATA/");
|
|
|
|
+ });
|
|
|
|
|
|
- boost::filesystem::create_directories(filePath.parent_path());
|
|
|
|
|
|
+ for (auto & filename : list)
|
|
|
|
+ {
|
|
|
|
+ const boost::filesystem::path filePath = outPath / (filename.getName() + ".TXT");
|
|
|
|
|
|
- boost::filesystem::ofstream file(filePath);
|
|
|
|
- auto text = CResourceHandler::get()->load(filename)->readAll();
|
|
|
|
|
|
+ boost::filesystem::create_directories(filePath.parent_path());
|
|
|
|
|
|
- file.write((char*)text.first.get(), text.second);
|
|
|
|
- }
|
|
|
|
|
|
+ boost::filesystem::ofstream file(filePath);
|
|
|
|
+ auto text = CResourceHandler::get()->load(filename)->readAll();
|
|
|
|
|
|
- printCommandMessage("\rExtracting done :)\n");
|
|
|
|
- printCommandMessage("Extracted files can be found in " + outPath.string() + " directory\n");
|
|
|
|
- }
|
|
|
|
- else if(commandName == "crash")
|
|
|
|
- {
|
|
|
|
- int *ptr = nullptr;
|
|
|
|
- *ptr = 666;
|
|
|
|
- //disaster!
|
|
|
|
- }
|
|
|
|
- else if(commandName == "mp" && adventureInt)
|
|
|
|
- {
|
|
|
|
- if(const CGHeroInstance *h = adventureInt->curHero())
|
|
|
|
- printCommandMessage(std::to_string(h->movement) + "; max: " + std::to_string(h->maxMovePoints(true)) + "/" + std::to_string(h->maxMovePoints(false)) + "\n");
|
|
|
|
- }
|
|
|
|
- else if(commandName == "bonuses")
|
|
|
|
- {
|
|
|
|
- bool jsonFormat = (message == "bonuses json");
|
|
|
|
- auto format = [jsonFormat](const BonusList & b) -> std::string
|
|
|
|
- {
|
|
|
|
- if(jsonFormat)
|
|
|
|
- return b.toJsonNode().toJson(true);
|
|
|
|
- std::ostringstream ss;
|
|
|
|
- ss << b;
|
|
|
|
- return ss.str();
|
|
|
|
- };
|
|
|
|
- printCommandMessage("Bonuses of " + adventureInt->curArmy()->getObjectName() + "\n");
|
|
|
|
- printCommandMessage(format(adventureInt->curArmy()->getBonusList()) + "\n");
|
|
|
|
-
|
|
|
|
- printCommandMessage("\nInherited bonuses:\n");
|
|
|
|
- TCNodes parents;
|
|
|
|
- adventureInt->curArmy()->getParents(parents);
|
|
|
|
- for(const CBonusSystemNode *parent : parents)
|
|
|
|
- {
|
|
|
|
- printCommandMessage(std::string("\nBonuses from ") + typeid(*parent).name() + "\n" + format(*parent->getAllBonuses(Selector::all, Selector::all)) + "\n");
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else if(commandName == "not dialog")
|
|
|
|
- {
|
|
|
|
- LOCPLINT->showingDialog->setn(false);
|
|
|
|
|
|
+ file.write((char*)text.first.get(), text.second);
|
|
}
|
|
}
|
|
- else if(commandName == "gui")
|
|
|
|
- {
|
|
|
|
- for(auto & child : GH.listInt)
|
|
|
|
- {
|
|
|
|
- const auto childPtr = child.get();
|
|
|
|
- if(const CIntObject * obj = dynamic_cast<const CIntObject *>(childPtr))
|
|
|
|
- printInfoAboutInterfaceObject(obj, 0);
|
|
|
|
- else
|
|
|
|
- printCommandMessage(std::string(typeid(childPtr).name()) + "\n");
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else if(commandName == "tell")
|
|
|
|
- {
|
|
|
|
- std::string what;
|
|
|
|
- int id1, id2;
|
|
|
|
- singleWordBuffer >> what >> id1 >> id2;
|
|
|
|
- if(what == "hs")
|
|
|
|
- {
|
|
|
|
- for(const CGHeroInstance *h : LOCPLINT->cb->getHeroesInfo())
|
|
|
|
- if(h->type->getIndex() == id1)
|
|
|
|
- if(const CArtifactInstance *a = h->getArt(ArtifactPosition(id2)))
|
|
|
|
- printCommandMessage(a->nodeName());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else if (commandName == "set")
|
|
|
|
- {
|
|
|
|
- std::string what, value;
|
|
|
|
- singleWordBuffer >> what;
|
|
|
|
|
|
|
|
- Settings config = settings.write["session"][what];
|
|
|
|
|
|
+ printCommandMessage("\rExtracting done :)\n");
|
|
|
|
+ printCommandMessage("Extracted files can be found in " + outPath.string() + " directory\n");
|
|
|
|
+}
|
|
|
|
|
|
- singleWordBuffer >> value;
|
|
|
|
|
|
+void ClientCommandManager::handleDef2bmpCommand(std::istringstream& singleWordBuffer)
|
|
|
|
+{
|
|
|
|
+ std::string URI;
|
|
|
|
+ singleWordBuffer >> URI;
|
|
|
|
+ std::unique_ptr<CAnimation> anim = std::make_unique<CAnimation>(URI);
|
|
|
|
+ anim->preload();
|
|
|
|
+ anim->exportBitmaps(VCMIDirs::get().userExtractedPath());
|
|
|
|
+}
|
|
|
|
|
|
- if (value == "on")
|
|
|
|
- {
|
|
|
|
- config->Bool() = true;
|
|
|
|
- printCommandMessage("Option " + what + " enabled!", ELogLevel::INFO);
|
|
|
|
- }
|
|
|
|
- else if (value == "off")
|
|
|
|
- {
|
|
|
|
- config->Bool() = false;
|
|
|
|
- printCommandMessage("Option " + what + " disabled!", ELogLevel::INFO);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else if(commandName == "unlock")
|
|
|
|
- {
|
|
|
|
- std::string mxname;
|
|
|
|
- singleWordBuffer >> mxname;
|
|
|
|
- if(mxname == "pim" && LOCPLINT)
|
|
|
|
- LOCPLINT->pim->unlock();
|
|
|
|
- }
|
|
|
|
- else if(commandName == "def2bmp")
|
|
|
|
- {
|
|
|
|
- std::string URI;
|
|
|
|
- singleWordBuffer >> URI;
|
|
|
|
- std::unique_ptr<CAnimation> anim = std::make_unique<CAnimation>(URI);
|
|
|
|
- anim->preload();
|
|
|
|
- anim->exportBitmaps(VCMIDirs::get().userExtractedPath());
|
|
|
|
- }
|
|
|
|
- else if(commandName == "extract")
|
|
|
|
- {
|
|
|
|
- std::string URI;
|
|
|
|
- singleWordBuffer >> URI;
|
|
|
|
|
|
+void ClientCommandManager::handleExtractCommand(std::istringstream& singleWordBuffer)
|
|
|
|
+{
|
|
|
|
+ std::string URI;
|
|
|
|
+ singleWordBuffer >> URI;
|
|
|
|
|
|
- if (CResourceHandler::get()->existsResource(ResourceID(URI)))
|
|
|
|
- {
|
|
|
|
- const boost::filesystem::path outPath = VCMIDirs::get().userExtractedPath() / URI;
|
|
|
|
|
|
+ if(CResourceHandler::get()->existsResource(ResourceID(URI)))
|
|
|
|
+ {
|
|
|
|
+ const boost::filesystem::path outPath = VCMIDirs::get().userExtractedPath() / URI;
|
|
|
|
|
|
- auto data = CResourceHandler::get()->load(ResourceID(URI))->readAll();
|
|
|
|
|
|
+ auto data = CResourceHandler::get()->load(ResourceID(URI))->readAll();
|
|
|
|
|
|
- boost::filesystem::create_directories(outPath.parent_path());
|
|
|
|
- boost::filesystem::ofstream outFile(outPath, boost::filesystem::ofstream::binary);
|
|
|
|
- outFile.write((char*)data.first.get(), data.second);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- printCommandMessage("File not found!", ELogLevel::ERROR);
|
|
|
|
|
|
+ boost::filesystem::create_directories(outPath.parent_path());
|
|
|
|
+ boost::filesystem::ofstream outFile(outPath, boost::filesystem::ofstream::binary);
|
|
|
|
+ outFile.write((char*)data.first.get(), data.second);
|
|
}
|
|
}
|
|
- else if(commandName == "setBattleAI")
|
|
|
|
|
|
+ else
|
|
|
|
+ printCommandMessage("File not found!", ELogLevel::ERROR);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::handleBonusesCommand(std::istringstream & singleWordBuffer)
|
|
|
|
+{
|
|
|
|
+ if(currentCallFromIngameConsole)
|
|
{
|
|
{
|
|
- std::string fname;
|
|
|
|
- singleWordBuffer >> fname;
|
|
|
|
- printCommandMessage("Will try loading that AI to see if it is correct name...\n");
|
|
|
|
- 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
|
|
|
|
- {
|
|
|
|
- Settings neutralAI = settings.write["server"]["neutralAI"];
|
|
|
|
- neutralAI->String() = fname;
|
|
|
|
- printCommandMessage("Setting changed, from now the battle ai will be " + fname + "!\n");
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- catch(std::exception &e)
|
|
|
|
- {
|
|
|
|
- printCommandMessage("Failed opening " + fname + ": " + e.what(), ELogLevel::WARN);
|
|
|
|
- printCommandMessage("Setting not changed, AI not found or invalid!", ELogLevel::WARN);
|
|
|
|
- }
|
|
|
|
|
|
+ printCommandMessage("Output for this command is too large for ingame chat! Please run it from client console.\n");
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
- else if(commandName == "autoskip")
|
|
|
|
|
|
+
|
|
|
|
+ std::string outputFormat;
|
|
|
|
+ singleWordBuffer >> outputFormat;
|
|
|
|
+
|
|
|
|
+ auto format = [outputFormat](const BonusList & b) -> std::string
|
|
{
|
|
{
|
|
- Settings session = settings.write["session"];
|
|
|
|
- session["autoSkip"].Bool() = !session["autoSkip"].Bool();
|
|
|
|
- }
|
|
|
|
- else if(commandName == "gosolo")
|
|
|
|
|
|
+ if(outputFormat == "json")
|
|
|
|
+ return b.toJsonNode().toJson(true);
|
|
|
|
+
|
|
|
|
+ std::ostringstream ss;
|
|
|
|
+ ss << b;
|
|
|
|
+ return ss.str();
|
|
|
|
+ };
|
|
|
|
+ printCommandMessage("Bonuses of " + adventureInt->curArmy()->getObjectName() + "\n");
|
|
|
|
+ printCommandMessage(format(adventureInt->curArmy()->getBonusList()) + "\n");
|
|
|
|
+
|
|
|
|
+ printCommandMessage("\nInherited bonuses:\n");
|
|
|
|
+ TCNodes parents;
|
|
|
|
+ adventureInt->curArmy()->getParents(parents);
|
|
|
|
+ for(const CBonusSystemNode *parent : parents)
|
|
{
|
|
{
|
|
- ClientCommandManager::handleGoSolo();
|
|
|
|
|
|
+ printCommandMessage(std::string("\nBonuses from ") + typeid(*parent).name() + "\n" + format(*parent->getAllBonuses(Selector::all, Selector::all)) + "\n");
|
|
}
|
|
}
|
|
- else if(commandName == "controlai")
|
|
|
|
- {
|
|
|
|
- std::string colorName;
|
|
|
|
- singleWordBuffer >> colorName;
|
|
|
|
- boost::to_lower(colorName);
|
|
|
|
|
|
+}
|
|
|
|
|
|
- ClientCommandManager::handleControlAi(colorName);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
|
|
+void ClientCommandManager::handleTellCommand(std::istringstream& singleWordBuffer)
|
|
|
|
+{
|
|
|
|
+ std::string what;
|
|
|
|
+ int id1, id2;
|
|
|
|
+ singleWordBuffer >> what >> id1 >> id2;
|
|
|
|
+
|
|
|
|
+ if(what == "hs")
|
|
{
|
|
{
|
|
- if (!commandName.empty() && !vstd::iswithin(commandName[0], 0, ' ')) // filter-out debugger/IDE noise
|
|
|
|
- printCommandMessage("Command not found :(", ELogLevel::ERROR);
|
|
|
|
|
|
+ for(const CGHeroInstance* h : LOCPLINT->cb->getHeroesInfo())
|
|
|
|
+ if(h->type->getIndex() == id1)
|
|
|
|
+ if(const CArtifactInstance* a = h->getArt(ArtifactPosition(id2)))
|
|
|
|
+ printCommandMessage(a->nodeName());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void ClientCommandManager::giveTurn(const PlayerColor &colorIdentifier)
|
|
|
|
|
|
+void ClientCommandManager::handleMpCommand()
|
|
{
|
|
{
|
|
- YourTurn yt;
|
|
|
|
- yt.player = colorIdentifier;
|
|
|
|
- yt.daysWithoutCastle = CSH->client->getPlayerState(colorIdentifier)->daysWithoutCastle;
|
|
|
|
-
|
|
|
|
- ApplyClientNetPackVisitor visitor(*CSH->client, *CSH->client->gameState());
|
|
|
|
- yt.visit(visitor);
|
|
|
|
|
|
+ if(const CGHeroInstance* h = adventureInt->curHero())
|
|
|
|
+ printCommandMessage(std::to_string(h->movement) + "; max: " + std::to_string(h->maxMovePoints(true)) + "/" + std::to_string(h->maxMovePoints(false)) + "\n");
|
|
}
|
|
}
|
|
|
|
|
|
-void ClientCommandManager::printInfoAboutInterfaceObject(const CIntObject *obj, int level)
|
|
|
|
|
|
+void ClientCommandManager::handleSetCommand(std::istringstream& singleWordBuffer)
|
|
{
|
|
{
|
|
- std::stringstream sbuffer;
|
|
|
|
- sbuffer << std::string(level, '\t');
|
|
|
|
|
|
+ std::string what, value;
|
|
|
|
+ singleWordBuffer >> what;
|
|
|
|
|
|
- sbuffer << typeid(*obj).name() << " *** ";
|
|
|
|
- if (obj->active)
|
|
|
|
|
|
+ Settings config = settings.write["session"][what];
|
|
|
|
+
|
|
|
|
+ singleWordBuffer >> value;
|
|
|
|
+
|
|
|
|
+ if(value == "on")
|
|
{
|
|
{
|
|
-#define PRINT(check, text) if (obj->active & CIntObject::check) sbuffer << text
|
|
|
|
- PRINT(LCLICK, 'L');
|
|
|
|
- PRINT(RCLICK, 'R');
|
|
|
|
- PRINT(HOVER, 'H');
|
|
|
|
- PRINT(MOVE, 'M');
|
|
|
|
- PRINT(KEYBOARD, 'K');
|
|
|
|
- PRINT(TIME, 'T');
|
|
|
|
- PRINT(GENERAL, 'A');
|
|
|
|
- PRINT(WHEEL, 'W');
|
|
|
|
- PRINT(DOUBLECLICK, 'D');
|
|
|
|
-#undef PRINT
|
|
|
|
|
|
+ config->Bool() = true;
|
|
|
|
+ printCommandMessage("Option " + what + " enabled!", ELogLevel::INFO);
|
|
}
|
|
}
|
|
- else
|
|
|
|
- sbuffer << "inactive";
|
|
|
|
- sbuffer << " at " << obj->pos.x <<"x"<< obj->pos.y;
|
|
|
|
- sbuffer << " (" << obj->pos.w <<"x"<< obj->pos.h << ")";
|
|
|
|
- printCommandMessage(sbuffer.str(), ELogLevel::INFO);
|
|
|
|
|
|
+ else if(value == "off")
|
|
|
|
+ {
|
|
|
|
+ config->Bool() = false;
|
|
|
|
+ printCommandMessage("Option " + what + " disabled!", ELogLevel::INFO);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
- for(const CIntObject *child : obj->children)
|
|
|
|
- printInfoAboutInterfaceObject(child, level+1);
|
|
|
|
|
|
+void ClientCommandManager::handleUnlockCommand(std::istringstream& singleWordBuffer)
|
|
|
|
+{
|
|
|
|
+ std::string mxname;
|
|
|
|
+ singleWordBuffer >> mxname;
|
|
|
|
+ if(mxname == "pim" && LOCPLINT)
|
|
|
|
+ LOCPLINT->pim->unlock();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::handleCrashCommand()
|
|
|
|
+{
|
|
|
|
+ int* ptr = nullptr;
|
|
|
|
+ *ptr = 666;
|
|
|
|
+ //disaster!
|
|
}
|
|
}
|
|
|
|
|
|
void ClientCommandManager::printCommandMessage(const std::string &commandMessage, ELogLevel::ELogLevel messageType)
|
|
void ClientCommandManager::printCommandMessage(const std::string &commandMessage, ELogLevel::ELogLevel messageType)
|
|
@@ -520,3 +492,131 @@ void ClientCommandManager::printCommandMessage(const std::string &commandMessage
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::printInfoAboutInterfaceObject(const CIntObject *obj, int level)
|
|
|
|
+{
|
|
|
|
+ std::stringstream sbuffer;
|
|
|
|
+ sbuffer << std::string(level, '\t');
|
|
|
|
+
|
|
|
|
+ sbuffer << typeid(*obj).name() << " *** ";
|
|
|
|
+ if (obj->active)
|
|
|
|
+ {
|
|
|
|
+#define PRINT(check, text) if (obj->active & CIntObject::check) sbuffer << text
|
|
|
|
+ PRINT(LCLICK, 'L');
|
|
|
|
+ PRINT(RCLICK, 'R');
|
|
|
|
+ PRINT(HOVER, 'H');
|
|
|
|
+ PRINT(MOVE, 'M');
|
|
|
|
+ PRINT(KEYBOARD, 'K');
|
|
|
|
+ PRINT(TIME, 'T');
|
|
|
|
+ PRINT(GENERAL, 'A');
|
|
|
|
+ PRINT(WHEEL, 'W');
|
|
|
|
+ PRINT(DOUBLECLICK, 'D');
|
|
|
|
+#undef PRINT
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ sbuffer << "inactive";
|
|
|
|
+ sbuffer << " at " << obj->pos.x <<"x"<< obj->pos.y;
|
|
|
|
+ sbuffer << " (" << obj->pos.w <<"x"<< obj->pos.h << ")";
|
|
|
|
+ printCommandMessage(sbuffer.str(), ELogLevel::INFO);
|
|
|
|
+
|
|
|
|
+ for(const CIntObject *child : obj->children)
|
|
|
|
+ printInfoAboutInterfaceObject(child, level+1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::giveTurn(const PlayerColor &colorIdentifier)
|
|
|
|
+{
|
|
|
|
+ YourTurn yt;
|
|
|
|
+ yt.player = colorIdentifier;
|
|
|
|
+ yt.daysWithoutCastle = CSH->client->getPlayerState(colorIdentifier)->daysWithoutCastle;
|
|
|
|
+
|
|
|
|
+ ApplyClientNetPackVisitor visitor(*CSH->client, *CSH->client->gameState());
|
|
|
|
+ yt.visit(visitor);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ClientCommandManager::processCommand(const std::string & message, bool calledFromIngameConsole)
|
|
|
|
+{
|
|
|
|
+ // split the message into individual words
|
|
|
|
+ std::istringstream singleWordBuffer;
|
|
|
|
+ singleWordBuffer.str(message);
|
|
|
|
+
|
|
|
|
+ // get command name, to be used for single word commands
|
|
|
|
+ std::string commandName;
|
|
|
|
+ singleWordBuffer >> commandName;
|
|
|
|
+
|
|
|
|
+ currentCallFromIngameConsole = calledFromIngameConsole;
|
|
|
|
+
|
|
|
|
+ if(message == std::string("die, fool"))
|
|
|
|
+ handleQuitCommand();
|
|
|
|
+
|
|
|
|
+ else if(commandName == "save")
|
|
|
|
+ handleSaveCommand(singleWordBuffer);
|
|
|
|
+
|
|
|
|
+ else if(commandName=="load")
|
|
|
|
+ handleLoadCommand(singleWordBuffer); // not implemented
|
|
|
|
+
|
|
|
|
+ else if(commandName == "gosolo")
|
|
|
|
+ handleGoSoloCommand();
|
|
|
|
+
|
|
|
|
+ else if(commandName == "autoskip")
|
|
|
|
+ handleAutoskipCommand();
|
|
|
|
+
|
|
|
|
+ else if(commandName == "controlai")
|
|
|
|
+ handleControlaiCommand(singleWordBuffer);
|
|
|
|
+
|
|
|
|
+ else if(commandName == "setBattleAI")
|
|
|
|
+ handleSetBattleAICommand(singleWordBuffer);
|
|
|
|
+
|
|
|
|
+ else if(commandName == "redraw")
|
|
|
|
+ handleRedrawCommand();
|
|
|
|
+
|
|
|
|
+ else if(commandName == "screen")
|
|
|
|
+ handleScreenCommand();
|
|
|
|
+
|
|
|
|
+ else if(commandName == "not dialog")
|
|
|
|
+ handleNotDialogCommand();
|
|
|
|
+
|
|
|
|
+ else if(commandName == "gui")
|
|
|
|
+ handleGuiCommand();
|
|
|
|
+
|
|
|
|
+ else if(message=="convert txt")
|
|
|
|
+ handleConvertTextCommand();
|
|
|
|
+
|
|
|
|
+ else if(message=="get config")
|
|
|
|
+ handleGetConfigCommand();
|
|
|
|
+
|
|
|
|
+ else if(message=="get scripts")
|
|
|
|
+ handleGetScriptsCommand();
|
|
|
|
+
|
|
|
|
+ else if(message=="get txt")
|
|
|
|
+ handleGetTextCommand();
|
|
|
|
+
|
|
|
|
+ else if(commandName == "def2bmp")
|
|
|
|
+ handleDef2bmpCommand(singleWordBuffer);
|
|
|
|
+
|
|
|
|
+ else if(commandName == "extract")
|
|
|
|
+ handleExtractCommand(singleWordBuffer);
|
|
|
|
+
|
|
|
|
+ else if(commandName == "bonuses")
|
|
|
|
+ handleBonusesCommand(singleWordBuffer);
|
|
|
|
+
|
|
|
|
+ else if(commandName == "tell")
|
|
|
|
+ handleTellCommand(singleWordBuffer);
|
|
|
|
+
|
|
|
|
+ else if(commandName == "mp" && adventureInt)
|
|
|
|
+ handleMpCommand();
|
|
|
|
+
|
|
|
|
+ else if (commandName == "set")
|
|
|
|
+ handleSetCommand(singleWordBuffer);
|
|
|
|
+
|
|
|
|
+ else if(commandName == "unlock")
|
|
|
|
+ handleUnlockCommand(singleWordBuffer);
|
|
|
|
+
|
|
|
|
+ else if(commandName == "crash")
|
|
|
|
+ handleCrashCommand();
|
|
|
|
+
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ if (!commandName.empty() && !vstd::iswithin(commandName[0], 0, ' ')) // filter-out debugger/IDE noise
|
|
|
|
+ printCommandMessage("Command not found :(", ELogLevel::ERROR);
|
|
|
|
+ }
|
|
|
|
+}
|