mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-15 01:24:45 +02:00
20
.editorconfig
Normal file
20
.editorconfig
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = tab
|
||||||
|
insert_final_newline = true
|
||||||
|
spelling_language = en-US
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[{*.py,CMakePresets.json}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.{md,yml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.ui]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 1
|
@ -10,6 +10,7 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
|
|
||||||
#include "../../lib/ArtifactUtils.h"
|
#include "../../lib/ArtifactUtils.h"
|
||||||
|
#include "../../lib/AsyncRunner.h"
|
||||||
#include "../../lib/UnlockGuard.h"
|
#include "../../lib/UnlockGuard.h"
|
||||||
#include "../../lib/StartInfo.h"
|
#include "../../lib/StartInfo.h"
|
||||||
#include "../../lib/entities/building/CBuilding.h"
|
#include "../../lib/entities/building/CBuilding.h"
|
||||||
@ -32,8 +33,6 @@
|
|||||||
#include "AIGateway.h"
|
#include "AIGateway.h"
|
||||||
#include "Goals/Goals.h"
|
#include "Goals/Goals.h"
|
||||||
|
|
||||||
static tbb::task_arena executeActionAsyncArena;
|
|
||||||
|
|
||||||
namespace NKAI
|
namespace NKAI
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -73,7 +72,7 @@ AIGateway::AIGateway()
|
|||||||
destinationTeleport = ObjectInstanceID();
|
destinationTeleport = ObjectInstanceID();
|
||||||
destinationTeleportPos = int3(-1);
|
destinationTeleportPos = int3(-1);
|
||||||
nullkiller.reset(new Nullkiller());
|
nullkiller.reset(new Nullkiller());
|
||||||
asyncTasks = std::make_unique<tbb::task_group>();
|
asyncTasks = std::make_unique<AsyncRunner>();
|
||||||
}
|
}
|
||||||
|
|
||||||
AIGateway::~AIGateway()
|
AIGateway::~AIGateway()
|
||||||
@ -593,11 +592,11 @@ void AIGateway::yourTurn(QueryID queryID)
|
|||||||
|
|
||||||
nullkiller->makingTurnInterrupption.reset();
|
nullkiller->makingTurnInterrupption.reset();
|
||||||
|
|
||||||
executeActionAsyncArena.enqueue(asyncTasks->defer([this]()
|
asyncTasks->run([this]()
|
||||||
{
|
{
|
||||||
ScopedThreadName guard("NKAI::makingTurn");
|
ScopedThreadName guard("NKAI::makingTurn");
|
||||||
makeTurn();
|
makeTurn();
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AIGateway::heroGotLevel(const CGHeroInstance * hero, PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID)
|
void AIGateway::heroGotLevel(const CGHeroInstance * hero, PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID)
|
||||||
@ -1608,13 +1607,13 @@ void AIGateway::executeActionAsync(const std::string & description, const std::f
|
|||||||
if (!asyncTasks)
|
if (!asyncTasks)
|
||||||
throw std::runtime_error("Attempt to execute task on shut down AI state!");
|
throw std::runtime_error("Attempt to execute task on shut down AI state!");
|
||||||
|
|
||||||
executeActionAsyncArena.enqueue(asyncTasks->defer([this, description, whatToDo]()
|
asyncTasks->run([this, description, whatToDo]()
|
||||||
{
|
{
|
||||||
ScopedThreadName guard("NKAI::" + description);
|
ScopedThreadName guard("NKAI::" + description);
|
||||||
SET_GLOBAL_STATE(this);
|
SET_GLOBAL_STATE(this);
|
||||||
std::shared_lock gsLock(CGameState::mutex);
|
std::shared_lock gsLock(CGameState::mutex);
|
||||||
whatToDo();
|
whatToDo();
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AIGateway::lostHero(HeroPtr h)
|
void AIGateway::lostHero(HeroPtr h)
|
||||||
|
@ -22,8 +22,9 @@
|
|||||||
#include "Pathfinding/AIPathfinder.h"
|
#include "Pathfinding/AIPathfinder.h"
|
||||||
#include "Engine/Nullkiller.h"
|
#include "Engine/Nullkiller.h"
|
||||||
|
|
||||||
#include <tbb/task_group.h>
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
#include <tbb/task_arena.h>
|
class AsyncRunner;
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
namespace NKAI
|
namespace NKAI
|
||||||
{
|
{
|
||||||
@ -74,7 +75,7 @@ public:
|
|||||||
AIStatus status;
|
AIStatus status;
|
||||||
std::string battlename;
|
std::string battlename;
|
||||||
std::shared_ptr<CCallback> myCb;
|
std::shared_ptr<CCallback> myCb;
|
||||||
std::unique_ptr<tbb::task_group> asyncTasks;
|
std::unique_ptr<AsyncRunner> asyncTasks;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjectInstanceID selectedObject;
|
ObjectInstanceID selectedObject;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "Goals/Goals.h"
|
#include "Goals/Goals.h"
|
||||||
|
|
||||||
#include "../../lib/ArtifactUtils.h"
|
#include "../../lib/ArtifactUtils.h"
|
||||||
|
#include "../../lib/AsyncRunner.h"
|
||||||
#include "../../lib/CThreadHelper.h"
|
#include "../../lib/CThreadHelper.h"
|
||||||
#include "../../lib/UnlockGuard.h"
|
#include "../../lib/UnlockGuard.h"
|
||||||
#include "../../lib/StartInfo.h"
|
#include "../../lib/StartInfo.h"
|
||||||
@ -37,8 +38,6 @@
|
|||||||
|
|
||||||
#include "AIhelper.h"
|
#include "AIhelper.h"
|
||||||
|
|
||||||
static tbb::task_arena executeActionAsyncArena;
|
|
||||||
|
|
||||||
extern FuzzyHelper * fh;
|
extern FuzzyHelper * fh;
|
||||||
|
|
||||||
const double SAFE_ATTACK_CONSTANT = 1.5;
|
const double SAFE_ATTACK_CONSTANT = 1.5;
|
||||||
@ -78,7 +77,7 @@ struct SetGlobalState
|
|||||||
VCAI::VCAI()
|
VCAI::VCAI()
|
||||||
{
|
{
|
||||||
LOG_TRACE(logAi);
|
LOG_TRACE(logAi);
|
||||||
asyncTasks = std::make_unique<tbb::task_group>();
|
asyncTasks = std::make_unique<AsyncRunner>();
|
||||||
destinationTeleport = ObjectInstanceID();
|
destinationTeleport = ObjectInstanceID();
|
||||||
destinationTeleportPos = int3(-1);
|
destinationTeleportPos = int3(-1);
|
||||||
|
|
||||||
@ -653,11 +652,11 @@ void VCAI::yourTurn(QueryID queryID)
|
|||||||
status.startedTurn();
|
status.startedTurn();
|
||||||
|
|
||||||
makingTurnInterrupption.reset();
|
makingTurnInterrupption.reset();
|
||||||
executeActionAsyncArena.enqueue(asyncTasks->defer([this]()
|
asyncTasks->run([this]()
|
||||||
{
|
{
|
||||||
ScopedThreadName guard("VCAI::makingTurn");
|
ScopedThreadName guard("VCAI::makingTurn");
|
||||||
makeTurn();
|
makeTurn();
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCAI::heroGotLevel(const CGHeroInstance * hero, PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID)
|
void VCAI::heroGotLevel(const CGHeroInstance * hero, PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID)
|
||||||
@ -2510,13 +2509,13 @@ void VCAI::executeActionAsync(const std::string & description, const std::functi
|
|||||||
if (!asyncTasks)
|
if (!asyncTasks)
|
||||||
throw std::runtime_error("Attempt to execute task on shut down AI state!");
|
throw std::runtime_error("Attempt to execute task on shut down AI state!");
|
||||||
|
|
||||||
executeActionAsyncArena.enqueue(asyncTasks->defer([this, description, whatToDo]()
|
asyncTasks->run([this, description, whatToDo]()
|
||||||
{
|
{
|
||||||
ScopedThreadName guard("VCAI::" + description);
|
ScopedThreadName guard("VCAI::" + description);
|
||||||
SET_GLOBAL_STATE(this);
|
SET_GLOBAL_STATE(this);
|
||||||
std::shared_lock gsLock(CGameState::mutex);
|
std::shared_lock gsLock(CGameState::mutex);
|
||||||
whatToDo();
|
whatToDo();
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCAI::lostHero(HeroPtr h)
|
void VCAI::lostHero(HeroPtr h)
|
||||||
|
@ -23,13 +23,11 @@
|
|||||||
#include "../../lib/spells/CSpellHandler.h"
|
#include "../../lib/spells/CSpellHandler.h"
|
||||||
#include "Pathfinding/AIPathfinder.h"
|
#include "Pathfinding/AIPathfinder.h"
|
||||||
|
|
||||||
#include <tbb/task_group.h>
|
|
||||||
#include <tbb/task_arena.h>
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
struct QuestInfo;
|
struct QuestInfo;
|
||||||
class PathfinderCache;
|
class PathfinderCache;
|
||||||
|
class AsyncRunner;
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
@ -108,7 +106,7 @@ public:
|
|||||||
|
|
||||||
std::shared_ptr<CCallback> myCb;
|
std::shared_ptr<CCallback> myCb;
|
||||||
|
|
||||||
std::unique_ptr<tbb::task_group> asyncTasks;
|
std::unique_ptr<AsyncRunner> asyncTasks;
|
||||||
ThreadInterruption makingTurnInterrupption;
|
ThreadInterruption makingTurnInterrupption;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -16,4 +16,3 @@ extern SDL_Renderer * mainRenderer;
|
|||||||
/// Defined in clientapp EntryPoint
|
/// Defined in clientapp EntryPoint
|
||||||
/// TODO: decide on better location for this method
|
/// TODO: decide on better location for this method
|
||||||
[[noreturn]] void handleFatalError(const std::string & message, bool terminate);
|
[[noreturn]] void handleFatalError(const std::string & message, bool terminate);
|
||||||
void handleQuit(bool ask = true);
|
|
||||||
|
@ -703,8 +703,6 @@ void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared
|
|||||||
entry->Bool() = true;
|
entry->Bool() = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GAME->mainmenu()->makeActiveInterface();
|
|
||||||
|
|
||||||
if(!ourCampaign->isCampaignFinished())
|
if(!ourCampaign->isCampaignFinished())
|
||||||
GAME->mainmenu()->openCampaignLobby(ourCampaign);
|
GAME->mainmenu()->openCampaignLobby(ourCampaign);
|
||||||
else
|
else
|
||||||
|
@ -23,20 +23,17 @@
|
|||||||
#include "media/CVideoHandler.h"
|
#include "media/CVideoHandler.h"
|
||||||
#include "media/CEmptyVideoPlayer.h"
|
#include "media/CEmptyVideoPlayer.h"
|
||||||
|
|
||||||
#include "CPlayerInterface.h"
|
|
||||||
#include "adventureMap/AdventureMapInterface.h"
|
#include "adventureMap/AdventureMapInterface.h"
|
||||||
#include "render/Canvas.h"
|
#include "render/Canvas.h"
|
||||||
#include "render/Colors.h"
|
#include "render/Colors.h"
|
||||||
#include "render/Graphics.h"
|
|
||||||
#include "render/IFont.h"
|
#include "render/IFont.h"
|
||||||
#include "render/EFont.h"
|
#include "render/EFont.h"
|
||||||
#include "renderSDL/ScreenHandler.h"
|
#include "renderSDL/ScreenHandler.h"
|
||||||
#include "renderSDL/RenderHandler.h"
|
#include "renderSDL/RenderHandler.h"
|
||||||
#include "CMT.h"
|
|
||||||
#include "GameEngineUser.h"
|
#include "GameEngineUser.h"
|
||||||
#include "battle/BattleInterface.h"
|
#include "battle/BattleInterface.h"
|
||||||
|
|
||||||
#include "../lib/CThreadHelper.h"
|
#include "../lib/AsyncRunner.h"
|
||||||
#include "../lib/CConfigHandler.h"
|
#include "../lib/CConfigHandler.h"
|
||||||
|
|
||||||
#include <SDL_render.h>
|
#include <SDL_render.h>
|
||||||
@ -58,7 +55,9 @@ ObjectConstruction::~ObjectConstruction()
|
|||||||
ENGINE->captureChildren = !ENGINE->createdObj.empty();
|
ENGINE->captureChildren = !ENGINE->createdObj.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameEngine::init()
|
GameEngine::GameEngine()
|
||||||
|
: captureChildren(false)
|
||||||
|
, fakeStatusBar(std::make_shared<EmptyStatusBar>())
|
||||||
{
|
{
|
||||||
inGuiThread = true;
|
inGuiThread = true;
|
||||||
|
|
||||||
@ -81,9 +80,11 @@ void GameEngine::init()
|
|||||||
|
|
||||||
soundPlayerInstance = std::make_unique<CSoundHandler>();
|
soundPlayerInstance = std::make_unique<CSoundHandler>();
|
||||||
musicPlayerInstance = std::make_unique<CMusicHandler>();
|
musicPlayerInstance = std::make_unique<CMusicHandler>();
|
||||||
sound().setVolume((ui32)settings["general"]["sound"].Float());
|
sound().setVolume(settings["general"]["sound"].Integer());
|
||||||
music().setVolume((ui32)settings["general"]["music"].Float());
|
music().setVolume(settings["general"]["music"].Integer());
|
||||||
cursorHandlerInstance = std::make_unique<CursorHandler>();
|
cursorHandlerInstance = std::make_unique<CursorHandler>();
|
||||||
|
|
||||||
|
asyncTasks = std::make_unique<AsyncRunner>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameEngine::handleEvents()
|
void GameEngine::handleEvents()
|
||||||
@ -104,9 +105,19 @@ void GameEngine::fakeMouseMove()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameEngine::renderFrame()
|
[[noreturn]] void GameEngine::mainLoop()
|
||||||
{
|
{
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
|
input().fetchEvents();
|
||||||
|
updateFrame();
|
||||||
|
screenHandlerInstance->presentScreenTexture();
|
||||||
|
framerate().framerateDelay(); // holds a constant FPS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameEngine::updateFrame()
|
||||||
|
{
|
||||||
std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
|
std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
|
||||||
|
|
||||||
engineUser->onUpdate();
|
engineUser->onUpdate();
|
||||||
@ -121,16 +132,6 @@ void GameEngine::renderFrame()
|
|||||||
|
|
||||||
windows().onFrameRendered();
|
windows().onFrameRendered();
|
||||||
ENGINE->cursor().update();
|
ENGINE->cursor().update();
|
||||||
}
|
|
||||||
|
|
||||||
screenHandlerInstance->presentScreenTexture();
|
|
||||||
framerate().framerateDelay(); // holds a constant FPS
|
|
||||||
}
|
|
||||||
|
|
||||||
GameEngine::GameEngine()
|
|
||||||
: captureChildren(false)
|
|
||||||
, fakeStatusBar(std::make_shared<EmptyStatusBar>())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameEngine::~GameEngine()
|
GameEngine::~GameEngine()
|
||||||
@ -239,7 +240,7 @@ std::shared_ptr<IStatusBar> GameEngine::statusbar()
|
|||||||
return locked;
|
return locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameEngine::setStatusbar(std::shared_ptr<IStatusBar> newStatusBar)
|
void GameEngine::setStatusbar(const std::shared_ptr<IStatusBar> & newStatusBar)
|
||||||
{
|
{
|
||||||
currentStatusBar = newStatusBar;
|
currentStatusBar = newStatusBar;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
class Point;
|
class Point;
|
||||||
|
class AsyncRunner;
|
||||||
class Rect;
|
class Rect;
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
@ -52,9 +53,14 @@ private:
|
|||||||
std::unique_ptr<IMusicPlayer> musicPlayerInstance;
|
std::unique_ptr<IMusicPlayer> musicPlayerInstance;
|
||||||
std::unique_ptr<CursorHandler> cursorHandlerInstance;
|
std::unique_ptr<CursorHandler> cursorHandlerInstance;
|
||||||
std::unique_ptr<IVideoPlayer> videoPlayerInstance;
|
std::unique_ptr<IVideoPlayer> videoPlayerInstance;
|
||||||
|
std::unique_ptr<AsyncRunner> asyncTasks;
|
||||||
|
|
||||||
IGameEngineUser *engineUser = nullptr;
|
IGameEngineUser *engineUser = nullptr;
|
||||||
|
|
||||||
|
void updateFrame();
|
||||||
|
void handleEvents(); //takes events from queue and calls interested objects
|
||||||
|
void drawFPSCounter(); // draws the FPS to the upper left corner of the screen
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::mutex interfaceMutex;
|
std::mutex interfaceMutex;
|
||||||
|
|
||||||
@ -66,6 +72,7 @@ public:
|
|||||||
EventDispatcher & events();
|
EventDispatcher & events();
|
||||||
InputHandler & input();
|
InputHandler & input();
|
||||||
|
|
||||||
|
AsyncRunner & async() { return *asyncTasks; }
|
||||||
IGameEngineUser & user() { return *engineUser; }
|
IGameEngineUser & user() { return *engineUser; }
|
||||||
ISoundPlayer & sound() { return *soundPlayerInstance; }
|
ISoundPlayer & sound() { return *soundPlayerInstance; }
|
||||||
IMusicPlayer & music() { return *musicPlayerInstance; }
|
IMusicPlayer & music() { return *musicPlayerInstance; }
|
||||||
@ -97,7 +104,9 @@ public:
|
|||||||
std::shared_ptr<IStatusBar> statusbar();
|
std::shared_ptr<IStatusBar> statusbar();
|
||||||
|
|
||||||
/// Set currently active status bar
|
/// Set currently active status bar
|
||||||
void setStatusbar(std::shared_ptr<IStatusBar>);
|
void setStatusbar(const std::shared_ptr<IStatusBar> &);
|
||||||
|
|
||||||
|
/// Sets engine user that is used as target of callback for events received by engine
|
||||||
void setEngineUser(IGameEngineUser * user);
|
void setEngineUser(IGameEngineUser * user);
|
||||||
|
|
||||||
bool captureChildren; //all newly created objects will get their parents from stack and will be added to parents children list
|
bool captureChildren; //all newly created objects will get their parents from stack and will be added to parents children list
|
||||||
@ -106,16 +115,17 @@ public:
|
|||||||
GameEngine();
|
GameEngine();
|
||||||
~GameEngine();
|
~GameEngine();
|
||||||
|
|
||||||
void init();
|
/// Performs main game loop till game shutdown
|
||||||
void renderFrame();
|
/// This method never returns, to abort main loop throw GameShutdownException
|
||||||
|
[[noreturn]] void mainLoop();
|
||||||
|
|
||||||
/// called whenever SDL_WINDOWEVENT_RESTORED is reported or the user selects a different resolution, requiring to center/resize all windows
|
/// called whenever SDL_WINDOWEVENT_RESTORED is reported or the user selects a different resolution, requiring to center/resize all windows
|
||||||
void onScreenResize(bool resolutionChanged);
|
void onScreenResize(bool resolutionChanged);
|
||||||
|
|
||||||
void handleEvents(); //takes events from queue and calls interested objects
|
/// Simulate mouse movement to force refresh UI state that updates on mouse move
|
||||||
void fakeMouseMove();
|
void fakeMouseMove();
|
||||||
void drawFPSCounter(); // draws the FPS to the upper left corner of the screen
|
|
||||||
|
|
||||||
|
/// Returns true for calls made from main (GUI) thread, false othervice
|
||||||
bool amIGuiThread();
|
bool amIGuiThread();
|
||||||
|
|
||||||
/// Calls provided functor in main thread on next execution frame
|
/// Calls provided functor in main thread on next execution frame
|
||||||
|
@ -20,6 +20,9 @@ public:
|
|||||||
/// Called on every game tick for game to update its state
|
/// Called on every game tick for game to update its state
|
||||||
virtual void onUpdate() = 0;
|
virtual void onUpdate() = 0;
|
||||||
|
|
||||||
|
/// Called when app shutdown has been requested in any way - exit button, Alt-F4, etc
|
||||||
|
virtual void onShutdownRequested(bool askForConfirmation) = 0;
|
||||||
|
|
||||||
/// Returns true if all input events should be captured and ignored
|
/// Returns true if all input events should be captured and ignored
|
||||||
virtual bool capturedAllEvents() = 0;
|
virtual bool capturedAllEvents() = 0;
|
||||||
};
|
};
|
||||||
|
@ -11,12 +11,16 @@
|
|||||||
#include "GameInstance.h"
|
#include "GameInstance.h"
|
||||||
|
|
||||||
#include "CPlayerInterface.h"
|
#include "CPlayerInterface.h"
|
||||||
|
#include "CMT.h"
|
||||||
#include "CServerHandler.h"
|
#include "CServerHandler.h"
|
||||||
#include "mapView/mapHandler.h"
|
#include "mapView/mapHandler.h"
|
||||||
#include "globalLobby/GlobalLobbyClient.h"
|
#include "globalLobby/GlobalLobbyClient.h"
|
||||||
#include "mainmenu/CMainMenu.h"
|
#include "mainmenu/CMainMenu.h"
|
||||||
|
#include "windows/InfoWindows.h"
|
||||||
|
|
||||||
#include "../lib/CConfigHandler.h"
|
#include "../lib/CConfigHandler.h"
|
||||||
|
#include "../lib/GameLibrary.h"
|
||||||
|
#include "../lib/texts/CGeneralTextHandler.h"
|
||||||
|
|
||||||
std::unique_ptr<GameInstance> GAME = nullptr;
|
std::unique_ptr<GameInstance> GAME = nullptr;
|
||||||
|
|
||||||
@ -93,3 +97,18 @@ bool GameInstance::capturedAllEvents()
|
|||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameInstance::onShutdownRequested(bool ask)
|
||||||
|
{
|
||||||
|
auto doQuit = [](){ throw GameShutdownException(); };
|
||||||
|
|
||||||
|
if(!ask)
|
||||||
|
doQuit();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (interface())
|
||||||
|
interface()->showYesNoDialog(LIBRARY->generaltexth->allTexts[69], doQuit, nullptr);
|
||||||
|
else
|
||||||
|
CInfoWindow::showYesNoDialog(LIBRARY->generaltexth->allTexts[69], {}, doQuit, {}, PlayerColor(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,6 +21,15 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
class INetworkHandler;
|
class INetworkHandler;
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
|
class GameShutdownException final : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char* what() const noexcept final
|
||||||
|
{
|
||||||
|
return "Game shutdown has been requested";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class GameInstance final : boost::noncopyable, public IGameEngineUser
|
class GameInstance final : boost::noncopyable, public IGameEngineUser
|
||||||
{
|
{
|
||||||
std::unique_ptr<CServerHandler> serverInstance;
|
std::unique_ptr<CServerHandler> serverInstance;
|
||||||
@ -45,6 +54,7 @@ public:
|
|||||||
void onGlobalLobbyInterfaceActivated() final;
|
void onGlobalLobbyInterfaceActivated() final;
|
||||||
void onUpdate() final;
|
void onUpdate() final;
|
||||||
bool capturedAllEvents() final;
|
bool capturedAllEvents() final;
|
||||||
|
void onShutdownRequested(bool askForConfirmation) final;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::unique_ptr<GameInstance> GAME;
|
extern std::unique_ptr<GameInstance> GAME;
|
||||||
|
@ -418,7 +418,7 @@ void ApplyClientNetPackVisitor::visitPlayerEndsGame(PlayerEndsGame & pack)
|
|||||||
{
|
{
|
||||||
logAi->info("Red player %s. Ending game.", pack.victoryLossCheckResult.victory() ? "won" : "lost");
|
logAi->info("Red player %s. Ending game.", pack.victoryLossCheckResult.victory() ? "won" : "lost");
|
||||||
|
|
||||||
handleQuit(settings["session"]["spectate"].Bool()); // if spectator is active ask to close client or not
|
GAME->onShutdownRequested(settings["session"]["spectate"].Bool()); // if spectator is active ask to close client or not
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,14 +354,8 @@ void AdventureMapShortcuts::quitGame()
|
|||||||
{
|
{
|
||||||
GAME->interface()->showYesNoDialog(
|
GAME->interface()->showYesNoDialog(
|
||||||
LIBRARY->generaltexth->allTexts[578],
|
LIBRARY->generaltexth->allTexts[578],
|
||||||
[]()
|
[](){ GAME->onShutdownRequested(false);},
|
||||||
{
|
nullptr
|
||||||
ENGINE->dispatchMainThread( []()
|
|
||||||
{
|
|
||||||
handleQuit(false);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
0
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "InputSourceGameController.h"
|
#include "InputSourceGameController.h"
|
||||||
|
|
||||||
#include "../GameEngine.h"
|
#include "../GameEngine.h"
|
||||||
|
#include "../GameEngineUser.h"
|
||||||
#include "../gui/CursorHandler.h"
|
#include "../gui/CursorHandler.h"
|
||||||
#include "../gui/EventDispatcher.h"
|
#include "../gui/EventDispatcher.h"
|
||||||
#include "../gui/MouseButton.h"
|
#include "../gui/MouseButton.h"
|
||||||
@ -194,9 +195,9 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
|
|||||||
{
|
{
|
||||||
std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
|
std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
|
||||||
#ifdef VCMI_ANDROID
|
#ifdef VCMI_ANDROID
|
||||||
handleQuit(false);
|
ENGINE->user().onShutdownRequested(false);
|
||||||
#else
|
#else
|
||||||
handleQuit(true);
|
ENGINE->user().onShutdownRequested(true);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -206,14 +207,14 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
|
|||||||
{
|
{
|
||||||
// FIXME: dead code? Looks like intercepted by OS/SDL and delivered as SDL_Quit instead?
|
// FIXME: dead code? Looks like intercepted by OS/SDL and delivered as SDL_Quit instead?
|
||||||
std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
|
std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
|
||||||
handleQuit(true);
|
ENGINE->user().onShutdownRequested(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ev.key.keysym.scancode == SDL_SCANCODE_AC_BACK && !settings["input"]["handleBackRightMouseButton"].Bool())
|
if(ev.key.keysym.scancode == SDL_SCANCODE_AC_BACK && !settings["input"]["handleBackRightMouseButton"].Bool())
|
||||||
{
|
{
|
||||||
std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
|
std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
|
||||||
handleQuit(true);
|
ENGINE->user().onShutdownRequested(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ bool mapSorter::operator()(const std::shared_ptr<ElementInfo> aaa, const std::sh
|
|||||||
{
|
{
|
||||||
if(boost::algorithm::starts_with(aaa->folderName, "..") || boost::algorithm::starts_with(bbb->folderName, ".."))
|
if(boost::algorithm::starts_with(aaa->folderName, "..") || boost::algorithm::starts_with(bbb->folderName, ".."))
|
||||||
return boost::algorithm::starts_with(aaa->folderName, "..");
|
return boost::algorithm::starts_with(aaa->folderName, "..");
|
||||||
return boost::ilexicographical_compare(aaa->folderName, bbb->folderName);
|
return TextOperations::compareLocalizedStrings(aaa->folderName, bbb->folderName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,13 +115,13 @@ bool mapSorter::operator()(const std::shared_ptr<ElementInfo> aaa, const std::sh
|
|||||||
return (a->victoryIconIndex < b->victoryIconIndex);
|
return (a->victoryIconIndex < b->victoryIconIndex);
|
||||||
break;
|
break;
|
||||||
case _name: //by name
|
case _name: //by name
|
||||||
return boost::ilexicographical_compare(a->name.toString(), b->name.toString());
|
return TextOperations::compareLocalizedStrings(aaa->name, bbb->name);
|
||||||
case _fileName: //by filename
|
case _fileName: //by filename
|
||||||
return boost::ilexicographical_compare(aaa->fileURI, bbb->fileURI);
|
return TextOperations::compareLocalizedStrings(aaa->fileURI, bbb->fileURI);
|
||||||
case _changeDate: //by changedate
|
case _changeDate: //by changedate
|
||||||
return aaa->lastWrite < bbb->lastWrite;
|
return aaa->lastWrite < bbb->lastWrite;
|
||||||
default:
|
default:
|
||||||
return boost::ilexicographical_compare(a->name.toString(), b->name.toString());
|
return TextOperations::compareLocalizedStrings(aaa->name, bbb->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //if we are sorting campaigns
|
else //if we are sorting campaigns
|
||||||
@ -131,9 +131,9 @@ bool mapSorter::operator()(const std::shared_ptr<ElementInfo> aaa, const std::sh
|
|||||||
case _numOfMaps: //by number of maps in campaign
|
case _numOfMaps: //by number of maps in campaign
|
||||||
return aaa->campaign->scenariosCount() < bbb->campaign->scenariosCount();
|
return aaa->campaign->scenariosCount() < bbb->campaign->scenariosCount();
|
||||||
case _name: //by name
|
case _name: //by name
|
||||||
return boost::ilexicographical_compare(aaa->campaign->getNameTranslated(), bbb->campaign->getNameTranslated());
|
return TextOperations::compareLocalizedStrings(aaa->campaign->getNameTranslated(), bbb->campaign->getNameTranslated());
|
||||||
default:
|
default:
|
||||||
return boost::ilexicographical_compare(aaa->campaign->getNameTranslated(), bbb->campaign->getNameTranslated());
|
return TextOperations::compareLocalizedStrings(aaa->campaign->getNameTranslated(), bbb->campaign->getNameTranslated());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,14 +64,6 @@
|
|||||||
|
|
||||||
ISelectionScreenInfo * SEL = nullptr;
|
ISelectionScreenInfo * SEL = nullptr;
|
||||||
|
|
||||||
static void do_quit()
|
|
||||||
{
|
|
||||||
ENGINE->dispatchMainThread([]()
|
|
||||||
{
|
|
||||||
handleQuit(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
CMenuScreen::CMenuScreen(const JsonNode & configNode)
|
CMenuScreen::CMenuScreen(const JsonNode & configNode)
|
||||||
: CWindowObject(BORDERED), config(configNode)
|
: CWindowObject(BORDERED), config(configNode)
|
||||||
{
|
{
|
||||||
@ -210,7 +202,7 @@ static std::function<void()> genCommand(CMenuScreen * menu, std::vector<std::str
|
|||||||
break;
|
break;
|
||||||
case 4: //exit
|
case 4: //exit
|
||||||
{
|
{
|
||||||
return []() { CInfoWindow::showYesNoDialog(LIBRARY->generaltexth->allTexts[69], std::vector<std::shared_ptr<CComponent>>(), do_quit, 0, PlayerColor(1)); };
|
return []() { CInfoWindow::showYesNoDialog(LIBRARY->generaltexth->allTexts[69], std::vector<std::shared_ptr<CComponent>>(), [](){GAME->onShutdownRequested(false);}, 0, PlayerColor(1)); };
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5: //highscores
|
case 5: //highscores
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "../media/IMusicPlayer.h"
|
#include "../media/IMusicPlayer.h"
|
||||||
#include "../media/ISoundPlayer.h"
|
#include "../media/ISoundPlayer.h"
|
||||||
#include "../GameEngine.h"
|
#include "../GameEngine.h"
|
||||||
|
#include "../gui/Shortcut.h"
|
||||||
#include "../widgets/TextControls.h"
|
#include "../widgets/TextControls.h"
|
||||||
#include "../widgets/VideoWidget.h"
|
#include "../widgets/VideoWidget.h"
|
||||||
#include "../widgets/Images.h"
|
#include "../widgets/Images.h"
|
||||||
@ -92,7 +93,7 @@ void CPrologEpilogVideo::show(Canvas & to)
|
|||||||
text->showAll(to); // blit text over video, if needed
|
text->showAll(to); // blit text over video, if needed
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPrologEpilogVideo::clickPressed(const Point & cursorPosition)
|
void CPrologEpilogVideo::exit()
|
||||||
{
|
{
|
||||||
ENGINE->music().setVolume(ENGINE->music().getVolume() * 2); // restore background volume
|
ENGINE->music().setVolume(ENGINE->music().getVolume() * 2); // restore background volume
|
||||||
close();
|
close();
|
||||||
@ -102,3 +103,14 @@ void CPrologEpilogVideo::clickPressed(const Point & cursorPosition)
|
|||||||
if(exitCb)
|
if(exitCb)
|
||||||
exitCb();
|
exitCb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPrologEpilogVideo::clickPressed(const Point & cursorPosition)
|
||||||
|
{
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPrologEpilogVideo::keyPressed(EShortcut key)
|
||||||
|
{
|
||||||
|
if(key == EShortcut::GLOBAL_RETURN)
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
@ -30,6 +30,8 @@ class CPrologEpilogVideo : public CWindowObject
|
|||||||
std::shared_ptr<VideoWidget> videoPlayer;
|
std::shared_ptr<VideoWidget> videoPlayer;
|
||||||
std::shared_ptr<CFilledTexture> backgroundAroundMenu;
|
std::shared_ptr<CFilledTexture> backgroundAroundMenu;
|
||||||
|
|
||||||
|
void exit();
|
||||||
|
|
||||||
bool voiceStopped = false;
|
bool voiceStopped = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -37,5 +39,6 @@ public:
|
|||||||
|
|
||||||
void tick(uint32_t msPassed) override;
|
void tick(uint32_t msPassed) override;
|
||||||
void clickPressed(const Point & cursorPosition) override;
|
void clickPressed(const Point & cursorPosition) override;
|
||||||
|
void keyPressed(EShortcut key) override;
|
||||||
void show(Canvas & to) override;
|
void show(Canvas & to) override;
|
||||||
};
|
};
|
||||||
|
@ -37,7 +37,8 @@ CAudioBase::~CAudioBase()
|
|||||||
--initializationCounter;
|
--initializationCounter;
|
||||||
|
|
||||||
if(initializationCounter == 0 && initializeSuccess)
|
if(initializationCounter == 0 && initializeSuccess)
|
||||||
|
{
|
||||||
Mix_CloseAudio();
|
Mix_CloseAudio();
|
||||||
|
|
||||||
initializeSuccess = false;
|
initializeSuccess = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,6 @@ CMusicHandler::~CMusicHandler()
|
|||||||
std::scoped_lock guard(mutex);
|
std::scoped_lock guard(mutex);
|
||||||
|
|
||||||
Mix_HookMusicFinished(nullptr);
|
Mix_HookMusicFinished(nullptr);
|
||||||
current->stop();
|
|
||||||
|
|
||||||
current.reset();
|
current.reset();
|
||||||
next.reset();
|
next.reset();
|
||||||
@ -233,8 +232,7 @@ MusicEntry::~MusicEntry()
|
|||||||
|
|
||||||
if(loop == 0 && Mix_FadingMusic() != MIX_NO_FADING)
|
if(loop == 0 && Mix_FadingMusic() != MIX_NO_FADING)
|
||||||
{
|
{
|
||||||
assert(0);
|
logGlobal->trace("Halting playback of music file %s", currentName.getOriginalName());
|
||||||
logGlobal->error("Attempt to delete music while fading out!");
|
|
||||||
Mix_HaltMusic();
|
Mix_HaltMusic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ CSoundHandler::~CSoundHandler()
|
|||||||
{
|
{
|
||||||
if(isInitialized())
|
if(isInitialized())
|
||||||
{
|
{
|
||||||
|
Mix_ChannelFinished(nullptr);
|
||||||
Mix_HaltChannel(-1);
|
Mix_HaltChannel(-1);
|
||||||
|
|
||||||
for(auto & chunk : soundChunks)
|
for(auto & chunk : soundChunks)
|
||||||
@ -63,6 +64,12 @@ CSoundHandler::~CSoundHandler()
|
|||||||
if(chunk.second.first)
|
if(chunk.second.first)
|
||||||
Mix_FreeChunk(chunk.second.first);
|
Mix_FreeChunk(chunk.second.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(auto & chunk : soundChunksRaw)
|
||||||
|
{
|
||||||
|
if(chunk.second.first)
|
||||||
|
Mix_FreeChunk(chunk.second.first);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,6 @@ public:
|
|||||||
/// Updates window state after fullscreen state has been changed in settings
|
/// Updates window state after fullscreen state has been changed in settings
|
||||||
virtual void onScreenResize() = 0;
|
virtual void onScreenResize() = 0;
|
||||||
|
|
||||||
/// De-initializes window state
|
|
||||||
virtual void close() = 0;
|
|
||||||
|
|
||||||
/// Fills screen with black color, erasing any existing content
|
/// Fills screen with black color, erasing any existing content
|
||||||
virtual void clearScreen() = 0;
|
virtual void clearScreen() = 0;
|
||||||
|
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
#include "../GameEngine.h"
|
#include "../GameEngine.h"
|
||||||
#include "../render/IScreenHandler.h"
|
#include "../render/IScreenHandler.h"
|
||||||
|
|
||||||
|
#include "../../lib/AsyncRunner.h"
|
||||||
#include "../../lib/CConfigHandler.h"
|
#include "../../lib/CConfigHandler.h"
|
||||||
|
|
||||||
#include <tbb/parallel_for.h>
|
#include <tbb/parallel_for.h>
|
||||||
#include <tbb/task_arena.h>
|
|
||||||
|
|
||||||
#include <SDL_image.h>
|
#include <SDL_image.h>
|
||||||
#include <SDL_surface.h>
|
#include <SDL_surface.h>
|
||||||
@ -256,8 +256,6 @@ std::shared_ptr<const ISharedImage> SDLImageShared::scaleInteger(int factor, SDL
|
|||||||
|
|
||||||
SDLImageShared::SDLImageShared(const SDLImageShared * from, int integerScaleFactor, EScalingAlgorithm algorithm)
|
SDLImageShared::SDLImageShared(const SDLImageShared * from, int integerScaleFactor, EScalingAlgorithm algorithm)
|
||||||
{
|
{
|
||||||
static tbb::task_arena upscalingArena;
|
|
||||||
|
|
||||||
upscalingInProgress = true;
|
upscalingInProgress = true;
|
||||||
|
|
||||||
auto scaler = std::make_shared<SDLImageScaler>(from->surf, Rect(from->margins, from->fullSize), true);
|
auto scaler = std::make_shared<SDLImageScaler>(from->surf, Rect(from->margins, from->fullSize), true);
|
||||||
@ -273,7 +271,7 @@ SDLImageShared::SDLImageShared(const SDLImageShared * from, int integerScaleFact
|
|||||||
};
|
};
|
||||||
|
|
||||||
if(settings["video"]["asyncUpscaling"].Bool())
|
if(settings["video"]["asyncUpscaling"].Bool())
|
||||||
upscalingArena.enqueue(scalingTask);
|
ENGINE->async().run(scalingTask);
|
||||||
else
|
else
|
||||||
scalingTask();
|
scalingTask();
|
||||||
}
|
}
|
||||||
@ -401,6 +399,9 @@ std::shared_ptr<const ISharedImage> SDLImageShared::horizontalFlip() const
|
|||||||
ret->margins.y = fullSize.y - surf->h - margins.y;
|
ret->margins.y = fullSize.y - surf->h - margins.y;
|
||||||
ret->fullSize = fullSize;
|
ret->fullSize = fullSize;
|
||||||
|
|
||||||
|
// erase our own reference
|
||||||
|
SDL_FreeSurface(flipped);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,6 +420,9 @@ std::shared_ptr<const ISharedImage> SDLImageShared::verticalFlip() const
|
|||||||
ret->margins.y = margins.y;
|
ret->margins.y = margins.y;
|
||||||
ret->fullSize = fullSize;
|
ret->fullSize = fullSize;
|
||||||
|
|
||||||
|
// erase our own reference
|
||||||
|
SDL_FreeSurface(flipped);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,6 +212,11 @@ ScreenHandler::ScreenHandler()
|
|||||||
else
|
else
|
||||||
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight");
|
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight");
|
||||||
|
|
||||||
|
#ifdef VCMI_IOS
|
||||||
|
if(!settings["general"]["ignoreMuteSwitch"].Bool())
|
||||||
|
SDL_SetHint(SDL_HINT_AUDIO_CATEGORY, "AVAudioSessionCategoryAmbient");
|
||||||
|
#endif
|
||||||
|
|
||||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER))
|
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER))
|
||||||
{
|
{
|
||||||
logGlobal->error("Something was wrong: %s", SDL_GetError());
|
logGlobal->error("Something was wrong: %s", SDL_GetError());
|
||||||
@ -595,7 +600,7 @@ void ScreenHandler::destroyWindow()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenHandler::close()
|
ScreenHandler::~ScreenHandler()
|
||||||
{
|
{
|
||||||
if(settings["general"]["notifications"].Bool())
|
if(settings["general"]["notifications"].Bool())
|
||||||
NotificationHandler::destroy();
|
NotificationHandler::destroy();
|
||||||
|
@ -96,13 +96,11 @@ public:
|
|||||||
|
|
||||||
/// Creates and initializes screen, window and SDL state
|
/// Creates and initializes screen, window and SDL state
|
||||||
ScreenHandler();
|
ScreenHandler();
|
||||||
|
~ScreenHandler();
|
||||||
|
|
||||||
/// Updates and potentially recreates target screen to match selected fullscreen status
|
/// Updates and potentially recreates target screen to match selected fullscreen status
|
||||||
void onScreenResize() final;
|
void onScreenResize() final;
|
||||||
|
|
||||||
/// De-initializes and destroys screen, window and SDL state
|
|
||||||
void close() final;
|
|
||||||
|
|
||||||
/// Fills screen with black color, erasing any existing content
|
/// Fills screen with black color, erasing any existing content
|
||||||
void clearScreen() final;
|
void clearScreen() final;
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return A->getNameTranslated() < B->getNameTranslated();
|
return TextOperations::compareLocalizedStrings(A->getNameTranslated(), B->getNameTranslated());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -241,12 +241,18 @@ void CSpellWindow::processSpells()
|
|||||||
mySpells.reserve(LIBRARY->spellh->objects.size());
|
mySpells.reserve(LIBRARY->spellh->objects.size());
|
||||||
for(auto const & spell : LIBRARY->spellh->objects)
|
for(auto const & spell : LIBRARY->spellh->objects)
|
||||||
{
|
{
|
||||||
bool searchTextFound = !searchBox || TextOperations::textSearchSimilar(searchBox->getText(), spell->getNameTranslated());
|
bool searchTextFound = !searchBox || TextOperations::textSearchSimilarityScore(searchBox->getText(), spell->getNameTranslated());
|
||||||
|
|
||||||
if(onSpellSelect)
|
if(onSpellSelect)
|
||||||
{
|
{
|
||||||
if(spell->isCombat() == openOnBattleSpells && !spell->isSpecial() && !spell->isCreatureAbility() && searchTextFound && (showAllSpells->isSelected() || myHero->canCastThisSpell(spell.get())))
|
if(spell->isCombat() == openOnBattleSpells
|
||||||
|
&& !spell->isSpecial()
|
||||||
|
&& !spell->isCreatureAbility()
|
||||||
|
&& searchTextFound
|
||||||
|
&& (showAllSpells->isSelected() || myHero->canCastThisSpell(spell.get())))
|
||||||
|
{
|
||||||
mySpells.push_back(spell.get());
|
mySpells.push_back(spell.get());
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "../render/Canvas.h"
|
#include "../render/Canvas.h"
|
||||||
#include "../render/IRenderHandler.h"
|
#include "../render/IRenderHandler.h"
|
||||||
#include "../render/IImage.h"
|
#include "../render/IImage.h"
|
||||||
|
#include "../render/IFont.h"
|
||||||
|
|
||||||
#include "../../CCallback.h"
|
#include "../../CCallback.h"
|
||||||
|
|
||||||
@ -1531,7 +1532,11 @@ CObjectListWindow::CObjectListWindow(const std::vector<int> & _items, std::share
|
|||||||
items.reserve(_items.size());
|
items.reserve(_items.size());
|
||||||
|
|
||||||
for(int id : _items)
|
for(int id : _items)
|
||||||
items.push_back(std::make_pair(id, GAME->interface()->cb->getObjInstance(ObjectInstanceID(id))->getObjectName()));
|
{
|
||||||
|
std::string objectName = GAME->interface()->cb->getObjInstance(ObjectInstanceID(id))->getObjectName();
|
||||||
|
trimTextIfTooWide(objectName, id);
|
||||||
|
items.emplace_back(id, objectName);
|
||||||
|
}
|
||||||
itemsVisible = items;
|
itemsVisible = items;
|
||||||
|
|
||||||
init(titleWidget_, _title, _descr, searchBoxEnabled);
|
init(titleWidget_, _title, _descr, searchBoxEnabled);
|
||||||
@ -1550,8 +1555,12 @@ CObjectListWindow::CObjectListWindow(const std::vector<std::string> & _items, st
|
|||||||
|
|
||||||
items.reserve(_items.size());
|
items.reserve(_items.size());
|
||||||
|
|
||||||
for(size_t i=0; i<_items.size(); i++)
|
for(size_t i = 0; i < _items.size(); i++)
|
||||||
items.push_back(std::make_pair(int(i), _items[i]));
|
{
|
||||||
|
std::string objectName = _items[i];
|
||||||
|
trimTextIfTooWide(objectName, static_cast<int>(i));
|
||||||
|
items.emplace_back(static_cast<int>(i), objectName);
|
||||||
|
}
|
||||||
itemsVisible = items;
|
itemsVisible = items;
|
||||||
|
|
||||||
init(titleWidget_, _title, _descr, searchBoxEnabled);
|
init(titleWidget_, _title, _descr, searchBoxEnabled);
|
||||||
@ -1570,7 +1579,7 @@ void CObjectListWindow::init(std::shared_ptr<CIntObject> titleWidget_, std::stri
|
|||||||
{
|
{
|
||||||
addChild(titleWidget.get());
|
addChild(titleWidget.get());
|
||||||
titleWidget->pos.x = pos.w/2 + pos.x - titleWidget->pos.w/2;
|
titleWidget->pos.x = pos.w/2 + pos.x - titleWidget->pos.w/2;
|
||||||
titleWidget->pos.y =75 + pos.y - titleWidget->pos.h/2;
|
titleWidget->pos.y = 75 + pos.y - titleWidget->pos.h/2;
|
||||||
}
|
}
|
||||||
list = std::make_shared<CListBox>(std::bind(&CObjectListWindow::genItem, this, _1),
|
list = std::make_shared<CListBox>(std::bind(&CObjectListWindow::genItem, this, _1),
|
||||||
Point(14, 151), Point(0, 25), 9, itemsVisible.size(), 0, 1, Rect(262, -32, 256, 256) );
|
Point(14, 151), Point(0, 25), 9, itemsVisible.size(), 0, 1, Rect(262, -32, 256, 256) );
|
||||||
@ -1590,13 +1599,57 @@ void CObjectListWindow::init(std::shared_ptr<CIntObject> titleWidget_, std::stri
|
|||||||
searchBoxDescription = std::make_shared<CLabel>(r.center().x, r.center().y, FONT_SMALL, ETextAlignment::CENTER, grayedColor, LIBRARY->generaltexth->translate("vcmi.spellBook.search"));
|
searchBoxDescription = std::make_shared<CLabel>(r.center().x, r.center().y, FONT_SMALL, ETextAlignment::CENTER, grayedColor, LIBRARY->generaltexth->translate("vcmi.spellBook.search"));
|
||||||
|
|
||||||
searchBox = std::make_shared<CTextInput>(r, FONT_SMALL, ETextAlignment::CENTER, true);
|
searchBox = std::make_shared<CTextInput>(r, FONT_SMALL, ETextAlignment::CENTER, true);
|
||||||
searchBox->setCallback([this](const std::string & text){
|
searchBox->setCallback(std::bind(&CObjectListWindow::itemsSearchCallback, this, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CObjectListWindow::trimTextIfTooWide(std::string & text, int id) const
|
||||||
|
{
|
||||||
|
int maxWidth = pos.w - 60; // 60 px for scrollbar and borders
|
||||||
|
std::string idStr = '(' + std::to_string(id) + ')';
|
||||||
|
const auto & font = ENGINE->renderHandler().loadFont(FONT_SMALL);
|
||||||
|
std::string suffix = " ... " + idStr;
|
||||||
|
|
||||||
|
if(font->getStringWidth(text) >= maxWidth)
|
||||||
|
{
|
||||||
|
logGlobal->warn("Mapobject name '%s' is too long and probably needs to be fixed! Trimming...",
|
||||||
|
text.substr(0, text.size() - idStr.size() + 1));
|
||||||
|
|
||||||
|
// Trim text until it fits
|
||||||
|
while(!text.empty())
|
||||||
|
{
|
||||||
|
std::string trimmedText = text + suffix;
|
||||||
|
|
||||||
|
if(font->getStringWidth(trimmedText) < maxWidth)
|
||||||
|
break;
|
||||||
|
|
||||||
|
TextOperations::trimRightUnicode(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
text += suffix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CObjectListWindow::itemsSearchCallback(const std::string & text)
|
||||||
|
{
|
||||||
searchBoxDescription->setEnabled(text.empty());
|
searchBoxDescription->setEnabled(text.empty());
|
||||||
|
|
||||||
itemsVisible.clear();
|
itemsVisible.clear();
|
||||||
for(auto & item : items)
|
std::vector<std::pair<int, decltype(items)::value_type>> rankedItems; // Store (score, item)
|
||||||
if(TextOperations::textSearchSimilar(text, item.second))
|
|
||||||
itemsVisible.push_back(item);
|
for(const auto & item : items)
|
||||||
|
{
|
||||||
|
if(auto score = TextOperations::textSearchSimilarityScore(text, item.second)) // Keep only relevant items
|
||||||
|
rankedItems.emplace_back(score.value(), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort: Lower score is better match
|
||||||
|
std::sort(rankedItems.begin(), rankedItems.end(), [](const auto & a, const auto & b)
|
||||||
|
{
|
||||||
|
return a.first < b.first;
|
||||||
|
});
|
||||||
|
|
||||||
|
for(const auto & rankedItem : rankedItems)
|
||||||
|
itemsVisible.push_back(rankedItem.second);
|
||||||
|
|
||||||
selected = 0;
|
selected = 0;
|
||||||
list->resize(itemsVisible.size());
|
list->resize(itemsVisible.size());
|
||||||
@ -1604,7 +1657,6 @@ void CObjectListWindow::init(std::shared_ptr<CIntObject> titleWidget_, std::stri
|
|||||||
ok->block(!itemsVisible.size());
|
ok->block(!itemsVisible.size());
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<CIntObject> CObjectListWindow::genItem(size_t index)
|
std::shared_ptr<CIntObject> CObjectListWindow::genItem(size_t index)
|
||||||
@ -1734,6 +1786,7 @@ void VideoWindow::clickPressed(const Point & cursorPosition)
|
|||||||
|
|
||||||
void VideoWindow::keyPressed(EShortcut key)
|
void VideoWindow::keyPressed(EShortcut key)
|
||||||
{
|
{
|
||||||
|
if(key == EShortcut::GLOBAL_RETURN)
|
||||||
exit(true);
|
exit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +197,8 @@ class CObjectListWindow : public CWindowObject
|
|||||||
std::vector< std::pair<int, std::string> > itemsVisible; //visible items present in list
|
std::vector< std::pair<int, std::string> > itemsVisible; //visible items present in list
|
||||||
|
|
||||||
void init(std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, bool searchBoxEnabled);
|
void init(std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, bool searchBoxEnabled);
|
||||||
|
void trimTextIfTooWide(std::string & text, int id) const; // trim item's text to fit within window's width
|
||||||
|
void itemsSearchCallback(const std::string & text);
|
||||||
void exitPressed();
|
void exitPressed();
|
||||||
public:
|
public:
|
||||||
size_t selected;//index of currently selected item
|
size_t selected;//index of currently selected item
|
||||||
|
@ -125,12 +125,9 @@ void SettingsMainWindow::quitGameButtonCallback()
|
|||||||
[this]()
|
[this]()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
ENGINE->dispatchMainThread( []()
|
ENGINE->user().onShutdownRequested(false);
|
||||||
{
|
|
||||||
handleQuit(false);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
0
|
nullptr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,24 +17,19 @@
|
|||||||
#include "../client/CMT.h"
|
#include "../client/CMT.h"
|
||||||
#include "../client/CPlayerInterface.h"
|
#include "../client/CPlayerInterface.h"
|
||||||
#include "../client/CServerHandler.h"
|
#include "../client/CServerHandler.h"
|
||||||
#include "../client/eventsSDL/InputHandler.h"
|
|
||||||
#include "../client/GameEngine.h"
|
#include "../client/GameEngine.h"
|
||||||
#include "../client/GameInstance.h"
|
#include "../client/GameInstance.h"
|
||||||
#include "../client/gui/CursorHandler.h"
|
#include "../client/gui/CursorHandler.h"
|
||||||
#include "../client/gui/WindowHandler.h"
|
#include "../client/gui/WindowHandler.h"
|
||||||
#include "../client/mainmenu/CMainMenu.h"
|
#include "../client/mainmenu/CMainMenu.h"
|
||||||
#include "../client/media/CEmptyVideoPlayer.h"
|
|
||||||
#include "../client/media/CMusicHandler.h"
|
|
||||||
#include "../client/media/CSoundHandler.h"
|
|
||||||
#include "../client/media/CVideoHandler.h"
|
|
||||||
#include "../client/render/Graphics.h"
|
#include "../client/render/Graphics.h"
|
||||||
#include "../client/render/IRenderHandler.h"
|
#include "../client/render/IRenderHandler.h"
|
||||||
#include "../client/render/IScreenHandler.h"
|
|
||||||
#include "../client/lobby/CBonusSelection.h"
|
|
||||||
#include "../client/windows/CMessage.h"
|
#include "../client/windows/CMessage.h"
|
||||||
#include "../client/windows/InfoWindows.h"
|
#include "../client/windows/InfoWindows.h"
|
||||||
|
|
||||||
|
#include "../lib/AsyncRunner.h"
|
||||||
#include "../lib/CConsoleHandler.h"
|
#include "../lib/CConsoleHandler.h"
|
||||||
|
#include "../lib/CConfigHandler.h"
|
||||||
#include "../lib/CThreadHelper.h"
|
#include "../lib/CThreadHelper.h"
|
||||||
#include "../lib/ExceptionsCommon.h"
|
#include "../lib/ExceptionsCommon.h"
|
||||||
#include "../lib/filesystem/Filesystem.h"
|
#include "../lib/filesystem/Filesystem.h"
|
||||||
@ -42,7 +37,6 @@
|
|||||||
#include "../lib/modding/IdentifierStorage.h"
|
#include "../lib/modding/IdentifierStorage.h"
|
||||||
#include "../lib/modding/CModHandler.h"
|
#include "../lib/modding/CModHandler.h"
|
||||||
#include "../lib/modding/ModDescription.h"
|
#include "../lib/modding/ModDescription.h"
|
||||||
#include "../lib/texts/CGeneralTextHandler.h"
|
|
||||||
#include "../lib/texts/MetaString.h"
|
#include "../lib/texts/MetaString.h"
|
||||||
#include "../lib/GameLibrary.h"
|
#include "../lib/GameLibrary.h"
|
||||||
#include "../lib/VCMIDirs.h"
|
#include "../lib/VCMIDirs.h"
|
||||||
@ -68,20 +62,13 @@ namespace po_style = boost::program_options::command_line_style;
|
|||||||
static std::atomic<bool> headlessQuit = false;
|
static std::atomic<bool> headlessQuit = false;
|
||||||
static std::optional<std::string> criticalInitializationError;
|
static std::optional<std::string> criticalInitializationError;
|
||||||
|
|
||||||
#ifndef VCMI_IOS
|
|
||||||
void processCommand(const std::string &message);
|
|
||||||
#endif
|
|
||||||
[[noreturn]] static void quitApplication();
|
|
||||||
static void mainLoop();
|
|
||||||
|
|
||||||
static CBasicLogConfigurator *logConfig;
|
|
||||||
|
|
||||||
static void init()
|
static void init()
|
||||||
{
|
{
|
||||||
CStopWatch tmh;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
loadDLLClasses();
|
CStopWatch tmh;
|
||||||
|
LIBRARY->initializeLibrary();
|
||||||
|
logGlobal->info("Initializing VCMI_Lib: %d ms", tmh.getDiff());
|
||||||
}
|
}
|
||||||
catch (const DataLoadingException & e)
|
catch (const DataLoadingException & e)
|
||||||
{
|
{
|
||||||
@ -89,8 +76,6 @@ static void init()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logGlobal->info("Initializing VCMI_Lib: %d ms", tmh.getDiff());
|
|
||||||
|
|
||||||
// Debug code to load all maps on start
|
// Debug code to load all maps on start
|
||||||
//ClientCommandManager commandController;
|
//ClientCommandManager commandController;
|
||||||
//commandController.processCommand("translate maps", false);
|
//commandController.processCommand("translate maps", false);
|
||||||
@ -241,7 +226,8 @@ int main(int argc, char * argv[])
|
|||||||
// Init filesystem and settings
|
// Init filesystem and settings
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
preinitDLL(false);
|
LIBRARY = new GameLibrary;
|
||||||
|
LIBRARY->initializeFilesystem(false);
|
||||||
}
|
}
|
||||||
catch (const DataLoadingException & e)
|
catch (const DataLoadingException & e)
|
||||||
{
|
{
|
||||||
@ -249,14 +235,14 @@ int main(int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
Settings session = settings.write["session"];
|
Settings session = settings.write["session"];
|
||||||
auto setSettingBool = [&](std::string key, std::string arg) {
|
auto setSettingBool = [&](const std::string & key, const std::string & arg) {
|
||||||
Settings s = settings.write(vstd::split(key, "/"));
|
Settings s = settings.write(vstd::split(key, "/"));
|
||||||
if(vm.count(arg))
|
if(vm.count(arg))
|
||||||
s->Bool() = true;
|
s->Bool() = true;
|
||||||
else if(s->isNull())
|
else if(s->isNull())
|
||||||
s->Bool() = false;
|
s->Bool() = false;
|
||||||
};
|
};
|
||||||
auto setSettingInteger = [&](std::string key, std::string arg, si64 defaultValue) {
|
auto setSettingInteger = [&](const std::string & key, const std::string & arg, si64 defaultValue) {
|
||||||
Settings s = settings.write(vstd::split(key, "/"));
|
Settings s = settings.write(vstd::split(key, "/"));
|
||||||
if(vm.count(arg))
|
if(vm.count(arg))
|
||||||
s->Integer() = vm[arg].as<si64>();
|
s->Integer() = vm[arg].as<si64>();
|
||||||
@ -294,7 +280,7 @@ int main(int argc, char * argv[])
|
|||||||
logGlobal->debug("settings = %s", settings.toJsonNode().toString());
|
logGlobal->debug("settings = %s", settings.toJsonNode().toString());
|
||||||
|
|
||||||
// Some basic data validation to produce better error messages in cases of incorrect install
|
// Some basic data validation to produce better error messages in cases of incorrect install
|
||||||
auto testFile = [](std::string filename, std::string message)
|
auto testFile = [](const std::string & filename, const std::string & message)
|
||||||
{
|
{
|
||||||
if (!CResourceHandler::get()->existsResource(ResourcePath(filename)))
|
if (!CResourceHandler::get()->existsResource(ResourcePath(filename)))
|
||||||
handleFatalError(message, false);
|
handleFatalError(message, false);
|
||||||
@ -308,12 +294,12 @@ int main(int argc, char * argv[])
|
|||||||
|
|
||||||
srand ( (unsigned int)time(nullptr) );
|
srand ( (unsigned int)time(nullptr) );
|
||||||
|
|
||||||
|
if(!settings["session"]["headless"].Bool())
|
||||||
ENGINE = std::make_unique<GameEngine>();
|
ENGINE = std::make_unique<GameEngine>();
|
||||||
|
|
||||||
if(!settings["session"]["headless"].Bool())
|
|
||||||
ENGINE->init();
|
|
||||||
|
|
||||||
GAME = std::make_unique<GameInstance>();
|
GAME = std::make_unique<GameInstance>();
|
||||||
|
|
||||||
|
if (ENGINE)
|
||||||
ENGINE->setEngineUser(GAME.get());
|
ENGINE->setEngineUser(GAME.get());
|
||||||
|
|
||||||
#ifndef VCMI_NO_THREADED_LOAD
|
#ifndef VCMI_NO_THREADED_LOAD
|
||||||
@ -345,7 +331,7 @@ int main(int argc, char * argv[])
|
|||||||
handleFatalError(criticalInitializationError.value(), false);
|
handleFatalError(criticalInitializationError.value(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!settings["session"]["headless"].Bool())
|
if (ENGINE)
|
||||||
{
|
{
|
||||||
pomtime.getDiff();
|
pomtime.getDiff();
|
||||||
graphics = new Graphics(); // should be before curh
|
graphics = new Graphics(); // should be before curh
|
||||||
@ -387,12 +373,17 @@ int main(int argc, char * argv[])
|
|||||||
GAME->mainmenu()->playMusic();
|
GAME->mainmenu()->playMusic();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> names;
|
#ifndef VCMI_UNIX
|
||||||
|
// on Linux, name of main thread is also name of our process. Which we don't want to change
|
||||||
|
setThreadName("MainGUI");
|
||||||
|
#endif
|
||||||
|
|
||||||
if(!settings["session"]["headless"].Bool())
|
try
|
||||||
|
{
|
||||||
|
if (ENGINE)
|
||||||
{
|
{
|
||||||
checkForModLoadingFailure();
|
checkForModLoadingFailure();
|
||||||
mainLoop();
|
ENGINE->mainLoop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -400,43 +391,14 @@ int main(int argc, char * argv[])
|
|||||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
|
||||||
quitApplication();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
catch (const GameShutdownException & )
|
||||||
}
|
|
||||||
|
|
||||||
static void mainLoop()
|
|
||||||
{
|
|
||||||
#ifndef VCMI_UNIX
|
|
||||||
// on Linux, name of main thread is also name of our process. Which we don't want to change
|
|
||||||
setThreadName("MainGUI");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while(1) //main SDL events loop
|
|
||||||
{
|
{
|
||||||
ENGINE->input().fetchEvents();
|
// no-op - just break out of main loop
|
||||||
ENGINE->renderFrame();
|
logGlobal->info("Main loop termination requested");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[[noreturn]] static void quitApplicationImmediately(int error_code)
|
|
||||||
{
|
|
||||||
// Perform quick exit without executing static destructors and let OS cleanup anything that we did not
|
|
||||||
// We generally don't care about them and this leads to numerous issues, e.g.
|
|
||||||
// destruction of locked mutexes (fails an assertion), even in third-party libraries (as well as native libs on Android)
|
|
||||||
// Android - std::quick_exit is available only starting from API level 21
|
|
||||||
// Mingw, macOS and iOS - std::quick_exit is unavailable (at least in current version of CI)
|
|
||||||
#if (defined(__ANDROID_API__) && __ANDROID_API__ < 21) || (defined(__MINGW32__)) || defined(VCMI_APPLE)
|
|
||||||
::exit(error_code);
|
|
||||||
#else
|
|
||||||
std::quick_exit(error_code);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
[[noreturn]] static void quitApplication()
|
|
||||||
{
|
|
||||||
GAME->server().endNetwork();
|
GAME->server().endNetwork();
|
||||||
|
|
||||||
if(!settings["session"]["headless"].Bool())
|
if(!settings["session"]["headless"].Bool())
|
||||||
@ -444,6 +406,7 @@ static void mainLoop()
|
|||||||
if(GAME->server().client)
|
if(GAME->server().client)
|
||||||
GAME->server().endGameplay();
|
GAME->server().endGameplay();
|
||||||
|
|
||||||
|
if (ENGINE)
|
||||||
ENGINE->windows().clear();
|
ENGINE->windows().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,51 +415,19 @@ static void mainLoop()
|
|||||||
if(!settings["session"]["headless"].Bool())
|
if(!settings["session"]["headless"].Bool())
|
||||||
{
|
{
|
||||||
CMessage::dispose();
|
CMessage::dispose();
|
||||||
|
|
||||||
vstd::clear_pointer(graphics);
|
vstd::clear_pointer(graphics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// must be executed before reset - since unique_ptr resets pointer to null before calling destructor
|
||||||
|
ENGINE->async().wait();
|
||||||
|
|
||||||
|
ENGINE.reset();
|
||||||
|
|
||||||
vstd::clear_pointer(LIBRARY);
|
vstd::clear_pointer(LIBRARY);
|
||||||
|
logConfigurator.deconfigure();
|
||||||
// sometimes leads to a hang. TODO: investigate
|
|
||||||
//vstd::clear_pointer(console);// should be removed after everything else since used by logging
|
|
||||||
|
|
||||||
if(!settings["session"]["headless"].Bool())
|
|
||||||
ENGINE->screenHandler().close();
|
|
||||||
|
|
||||||
if(logConfig != nullptr)
|
|
||||||
{
|
|
||||||
logConfig->deconfigure();
|
|
||||||
delete logConfig;
|
|
||||||
logConfig = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ENGINE.reset();
|
|
||||||
|
|
||||||
std::cout << "Ending...\n";
|
std::cout << "Ending...\n";
|
||||||
quitApplicationImmediately(0);
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
void handleQuit(bool ask)
|
|
||||||
{
|
|
||||||
if(!ask)
|
|
||||||
{
|
|
||||||
if(settings["session"]["headless"].Bool())
|
|
||||||
{
|
|
||||||
headlessQuit = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
quitApplication();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GAME->interface())
|
|
||||||
GAME->interface()->showYesNoDialog(LIBRARY->generaltexth->allTexts[69], quitApplication, nullptr);
|
|
||||||
else
|
|
||||||
CInfoWindow::showYesNoDialog(LIBRARY->generaltexth->allTexts[69], {}, quitApplication, {}, PlayerColor(1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Notify user about encountered fatal error and terminate the game
|
/// Notify user about encountered fatal error and terminate the game
|
||||||
@ -513,5 +444,5 @@ void handleFatalError(const std::string & message, bool terminate)
|
|||||||
if (terminate)
|
if (terminate)
|
||||||
throw std::runtime_error(message);
|
throw std::runtime_error(message);
|
||||||
else
|
else
|
||||||
quitApplicationImmediately(1);
|
::exit(1);
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,8 @@
|
|||||||
"audioMuteFocus",
|
"audioMuteFocus",
|
||||||
"enableOverlay",
|
"enableOverlay",
|
||||||
"lastKindomInterface",
|
"lastKindomInterface",
|
||||||
"enableSubtitle"
|
"enableSubtitle",
|
||||||
|
"ignoreMuteSwitch"
|
||||||
],
|
],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"playerName" : {
|
"playerName" : {
|
||||||
@ -161,6 +162,10 @@
|
|||||||
"enableSubtitle" : {
|
"enableSubtitle" : {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
|
},
|
||||||
|
"ignoreMuteSwitch" : {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -130,6 +130,10 @@ void CSettingsView::loadSettings()
|
|||||||
ui->labelHandleBackRightMouseButton->hide();
|
ui->labelHandleBackRightMouseButton->hide();
|
||||||
ui->buttonAllowPortrait->hide();
|
ui->buttonAllowPortrait->hide();
|
||||||
ui->labelAllowPortrait->hide();
|
ui->labelAllowPortrait->hide();
|
||||||
|
#endif
|
||||||
|
#ifndef VCMI_IOS
|
||||||
|
ui->labelIgnoreMuteSwitch->hide();
|
||||||
|
ui->buttonIgnoreMuteSwitch->hide();
|
||||||
#endif
|
#endif
|
||||||
fillValidScalingRange();
|
fillValidScalingRange();
|
||||||
|
|
||||||
@ -224,6 +228,8 @@ void CSettingsView::loadToggleButtonSettings()
|
|||||||
|
|
||||||
setCheckbuttonState(ui->buttonHandleBackRightMouseButton, settings["input"]["handleBackRightMouseButton"].Bool());
|
setCheckbuttonState(ui->buttonHandleBackRightMouseButton, settings["input"]["handleBackRightMouseButton"].Bool());
|
||||||
|
|
||||||
|
setCheckbuttonState(ui->buttonIgnoreMuteSwitch, settings["general"]["ignoreMuteSwitch"].Bool());
|
||||||
|
|
||||||
std::string cursorType = settings["video"]["cursor"].String();
|
std::string cursorType = settings["video"]["cursor"].String();
|
||||||
int cursorTypeIndex = vstd::find_pos(cursorTypesList, cursorType);
|
int cursorTypeIndex = vstd::find_pos(cursorTypesList, cursorType);
|
||||||
setCheckbuttonState(ui->buttonCursorType, cursorTypeIndex);
|
setCheckbuttonState(ui->buttonCursorType, cursorTypeIndex);
|
||||||
@ -866,3 +872,9 @@ void CSettingsView::on_buttonHandleBackRightMouseButton_toggled(bool checked)
|
|||||||
updateCheckbuttonText(ui->buttonHandleBackRightMouseButton);
|
updateCheckbuttonText(ui->buttonHandleBackRightMouseButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSettingsView::on_buttonIgnoreMuteSwitch_toggled(bool checked)
|
||||||
|
{
|
||||||
|
Settings node = settings.write["general"]["ignoreMuteSwitch"];
|
||||||
|
node->Bool() = checked;
|
||||||
|
updateCheckbuttonText(ui->buttonIgnoreMuteSwitch);
|
||||||
|
}
|
||||||
|
@ -91,18 +91,13 @@ private slots:
|
|||||||
void on_buttonFontScalable_clicked(bool checked);
|
void on_buttonFontScalable_clicked(bool checked);
|
||||||
void on_buttonFontOriginal_clicked(bool checked);
|
void on_buttonFontOriginal_clicked(bool checked);
|
||||||
|
|
||||||
|
|
||||||
void on_buttonValidationOff_clicked(bool checked);
|
void on_buttonValidationOff_clicked(bool checked);
|
||||||
|
|
||||||
void on_buttonValidationBasic_clicked(bool checked);
|
void on_buttonValidationBasic_clicked(bool checked);
|
||||||
|
|
||||||
void on_buttonValidationFull_clicked(bool checked);
|
void on_buttonValidationFull_clicked(bool checked);
|
||||||
|
|
||||||
void on_sliderScalingCursor_valueChanged(int value);
|
void on_sliderScalingCursor_valueChanged(int value);
|
||||||
|
|
||||||
void on_buttonScalingAuto_toggled(bool checked);
|
void on_buttonScalingAuto_toggled(bool checked);
|
||||||
|
|
||||||
void on_buttonHandleBackRightMouseButton_toggled(bool checked);
|
void on_buttonHandleBackRightMouseButton_toggled(bool checked);
|
||||||
|
void on_buttonIgnoreMuteSwitch_toggled(bool checked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::CSettingsView * ui;
|
Ui::CSettingsView * ui;
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="62" column="0">
|
<item row="63" column="0">
|
||||||
<widget class="QLabel" name="labelModsValidation">
|
<widget class="QLabel" name="labelModsValidation">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Mods Validation</string>
|
<string>Mods Validation</string>
|
||||||
@ -105,7 +105,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="45" column="1" colspan="5">
|
<item row="46" column="1" colspan="5">
|
||||||
<widget class="QSlider" name="sliderControllerSticksSensitivity">
|
<widget class="QSlider" name="sliderControllerSticksSensitivity">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>500</number>
|
<number>500</number>
|
||||||
@ -133,7 +133,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="37" column="1" colspan="5">
|
<item row="38" column="1" colspan="5">
|
||||||
<widget class="QPushButton" name="pushButtonResetTutorialTouchscreen">
|
<widget class="QPushButton" name="pushButtonResetTutorialTouchscreen">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Reset</string>
|
<string>Reset</string>
|
||||||
@ -147,7 +147,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="41" column="1" colspan="5">
|
<item row="42" column="1" colspan="5">
|
||||||
<widget class="QSlider" name="sliderLongTouchDuration">
|
<widget class="QSlider" name="sliderLongTouchDuration">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>500</number>
|
<number>500</number>
|
||||||
@ -172,7 +172,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="56" column="1">
|
<item row="57" column="1">
|
||||||
<widget class="QToolButton" name="buttonAutoCheck">
|
<widget class="QToolButton" name="buttonAutoCheck">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -239,7 +239,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="57" column="1">
|
<item row="58" column="1">
|
||||||
<widget class="QToolButton" name="buttonRepositoryDefault">
|
<widget class="QToolButton" name="buttonRepositoryDefault">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -268,14 +268,14 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="40" column="0">
|
<item row="41" column="0">
|
||||||
<widget class="QLabel" name="labelHapticFeedback">
|
<widget class="QLabel" name="labelHapticFeedback">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Haptic Feedback</string>
|
<string>Haptic Feedback</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="43" column="0">
|
<item row="44" column="0">
|
||||||
<widget class="QLabel" name="labelToleranceDistanceTouch">
|
<widget class="QLabel" name="labelToleranceDistanceTouch">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Touch Tap Tolerance</string>
|
<string>Touch Tap Tolerance</string>
|
||||||
@ -288,7 +288,7 @@
|
|||||||
<item row="1" column="1" colspan="5">
|
<item row="1" column="1" colspan="5">
|
||||||
<widget class="QComboBox" name="comboBoxLanguage"/>
|
<widget class="QComboBox" name="comboBoxLanguage"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="60" column="1" colspan="5">
|
<item row="61" column="1" colspan="5">
|
||||||
<widget class="QSpinBox" name="spinBoxNetworkPortLobby">
|
<widget class="QSpinBox" name="spinBoxNetworkPortLobby">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>1024</number>
|
<number>1024</number>
|
||||||
@ -301,7 +301,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="62" column="5">
|
<item row="63" column="5">
|
||||||
<widget class="QToolButton" name="buttonValidationFull">
|
<widget class="QToolButton" name="buttonValidationFull">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -326,7 +326,7 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="44" column="0">
|
<item row="45" column="0">
|
||||||
<widget class="QLabel" name="labelInputMouse_3">
|
<widget class="QLabel" name="labelInputMouse_3">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
@ -379,7 +379,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="49" column="1" colspan="5">
|
<item row="50" column="1" colspan="5">
|
||||||
<widget class="QComboBox" name="comboBoxEnemyPlayerAI">
|
<widget class="QComboBox" name="comboBoxEnemyPlayerAI">
|
||||||
<property name="currentText">
|
<property name="currentText">
|
||||||
<string notr="true">VCAI</string>
|
<string notr="true">VCAI</string>
|
||||||
@ -396,7 +396,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="57" column="2" colspan="4">
|
<item row="58" column="2" colspan="4">
|
||||||
<widget class="QLineEdit" name="lineEditRepositoryDefault">
|
<widget class="QLineEdit" name="lineEditRepositoryDefault">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true"/>
|
<string notr="true"/>
|
||||||
@ -406,7 +406,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="50" column="1" colspan="5">
|
<item row="51" column="1" colspan="5">
|
||||||
<widget class="QComboBox" name="comboBoxAlliedPlayerAI">
|
<widget class="QComboBox" name="comboBoxAlliedPlayerAI">
|
||||||
<property name="currentText">
|
<property name="currentText">
|
||||||
<string notr="true">VCAI</string>
|
<string notr="true">VCAI</string>
|
||||||
@ -430,7 +430,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="48" column="0">
|
<item row="49" column="0">
|
||||||
<widget class="QLabel" name="labelArtificialIntelligence">
|
<widget class="QLabel" name="labelArtificialIntelligence">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
@ -445,7 +445,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="57" column="0">
|
<item row="58" column="0">
|
||||||
<widget class="QLabel" name="labelRepositoryDefault">
|
<widget class="QLabel" name="labelRepositoryDefault">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Default repository</string>
|
<string>Default repository</string>
|
||||||
@ -471,7 +471,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="39" column="0">
|
<item row="40" column="0">
|
||||||
<widget class="QLabel" name="labelRelativeCursorSpeed">
|
<widget class="QLabel" name="labelRelativeCursorSpeed">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Relative Pointer Speed</string>
|
<string>Relative Pointer Speed</string>
|
||||||
@ -485,7 +485,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="55" column="1" colspan="5">
|
<item row="56" column="1" colspan="5">
|
||||||
<widget class="QToolButton" name="buttonIgnoreSslErrors">
|
<widget class="QToolButton" name="buttonIgnoreSslErrors">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -588,7 +588,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="58" column="1">
|
<item row="59" column="1">
|
||||||
<widget class="QToolButton" name="buttonRepositoryExtra">
|
<widget class="QToolButton" name="buttonRepositoryExtra">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
@ -607,21 +607,21 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="56" column="2" colspan="4">
|
<item row="57" column="2" colspan="4">
|
||||||
<widget class="QPushButton" name="refreshRepositoriesButton">
|
<widget class="QPushButton" name="refreshRepositoriesButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Refresh now</string>
|
<string>Refresh now</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="50" column="0">
|
<item row="51" column="0">
|
||||||
<widget class="QLabel" name="labelAlliedPlayerAI">
|
<widget class="QLabel" name="labelAlliedPlayerAI">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Adventure Map Allies</string>
|
<string>Adventure Map Allies</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="51" column="0">
|
<item row="52" column="0">
|
||||||
<widget class="QLabel" name="labelNeutralAI">
|
<widget class="QLabel" name="labelNeutralAI">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Neutral AI in battles</string>
|
<string>Neutral AI in battles</string>
|
||||||
@ -659,7 +659,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="59" column="1" colspan="5">
|
<item row="60" column="1" colspan="5">
|
||||||
<widget class="QLineEdit" name="lineEditGameLobbyHost">
|
<widget class="QLineEdit" name="lineEditGameLobbyHost">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true"/>
|
<string notr="true"/>
|
||||||
@ -673,7 +673,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="38" column="0">
|
<item row="39" column="0">
|
||||||
<widget class="QLabel" name="labelRelativeCursorMode">
|
<widget class="QLabel" name="labelRelativeCursorMode">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use Relative Pointer Mode</string>
|
<string>Use Relative Pointer Mode</string>
|
||||||
@ -683,14 +683,14 @@
|
|||||||
<item row="7" column="1" colspan="5">
|
<item row="7" column="1" colspan="5">
|
||||||
<widget class="QSpinBox" name="spinBoxAutoSaveLimit"/>
|
<widget class="QSpinBox" name="spinBoxAutoSaveLimit"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="52" column="0">
|
<item row="53" column="0">
|
||||||
<widget class="QLabel" name="labelFriendlyAI">
|
<widget class="QLabel" name="labelFriendlyAI">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Autocombat AI in battles</string>
|
<string>Autocombat AI in battles</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="62" column="1" colspan="2">
|
<item row="63" column="1" colspan="2">
|
||||||
<widget class="QToolButton" name="buttonValidationOff">
|
<widget class="QToolButton" name="buttonValidationOff">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -715,7 +715,7 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="33" column="0">
|
<item row="34" column="0">
|
||||||
<widget class="QLabel" name="labelInputMouse">
|
<widget class="QLabel" name="labelInputMouse">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
@ -737,7 +737,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="40" column="1" colspan="5">
|
<item row="41" column="1" colspan="5">
|
||||||
<widget class="QToolButton" name="buttonHapticFeedback">
|
<widget class="QToolButton" name="buttonHapticFeedback">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
@ -768,7 +768,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="58" column="0">
|
<item row="59" column="0">
|
||||||
<widget class="QLabel" name="labelRepositoryExtra">
|
<widget class="QLabel" name="labelRepositoryExtra">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Additional repository</string>
|
<string>Additional repository</string>
|
||||||
@ -791,7 +791,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="49" column="0">
|
<item row="50" column="0">
|
||||||
<widget class="QLabel" name="labelEnemyPlayerAI">
|
<widget class="QLabel" name="labelEnemyPlayerAI">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Adventure Map Enemies</string>
|
<string>Adventure Map Enemies</string>
|
||||||
@ -819,7 +819,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="36" column="0">
|
<item row="37" column="0">
|
||||||
<widget class="QLabel" name="labelInputMouse_2">
|
<widget class="QLabel" name="labelInputMouse_2">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
@ -853,7 +853,7 @@
|
|||||||
<item row="24" column="1">
|
<item row="24" column="1">
|
||||||
<widget class="QLabel" name="labelScalingCursorValue"/>
|
<widget class="QLabel" name="labelScalingCursorValue"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="38" column="1" colspan="5">
|
<item row="39" column="1" colspan="5">
|
||||||
<widget class="QToolButton" name="buttonRelativeCursorMode">
|
<widget class="QToolButton" name="buttonRelativeCursorMode">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
@ -876,28 +876,28 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="59" column="0">
|
<item row="60" column="0">
|
||||||
<widget class="QLabel" name="labelGameLobbyHost">
|
<widget class="QLabel" name="labelGameLobbyHost">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Online Lobby address</string>
|
<string>Online Lobby address</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="60" column="0">
|
<item row="61" column="0">
|
||||||
<widget class="QLabel" name="labelNetworkPortLobby">
|
<widget class="QLabel" name="labelNetworkPortLobby">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Online Lobby port</string>
|
<string>Online Lobby port</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="47" column="0">
|
<item row="48" column="0">
|
||||||
<widget class="QLabel" name="labelToleranceDistanceController">
|
<widget class="QLabel" name="labelToleranceDistanceController">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Controller Click Tolerance</string>
|
<string>Controller Click Tolerance</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="51" column="1" colspan="5">
|
<item row="52" column="1" colspan="5">
|
||||||
<widget class="QComboBox" name="comboBoxNeutralAI">
|
<widget class="QComboBox" name="comboBoxNeutralAI">
|
||||||
<property name="currentText">
|
<property name="currentText">
|
||||||
<string notr="true">BattleAI</string>
|
<string notr="true">BattleAI</string>
|
||||||
@ -933,7 +933,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="55" column="0">
|
<item row="56" column="0">
|
||||||
<widget class="QLabel" name="labelIgnoreSslErrors">
|
<widget class="QLabel" name="labelIgnoreSslErrors">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Ignore SSL errors</string>
|
<string>Ignore SSL errors</string>
|
||||||
@ -943,14 +943,14 @@
|
|||||||
<item row="21" column="1" colspan="5">
|
<item row="21" column="1" colspan="5">
|
||||||
<widget class="QComboBox" name="comboBoxDisplayIndex"/>
|
<widget class="QComboBox" name="comboBoxDisplayIndex"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="37" column="0">
|
<item row="38" column="0">
|
||||||
<widget class="QLabel" name="labelResetTutorialTouchscreen">
|
<widget class="QLabel" name="labelResetTutorialTouchscreen">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show Tutorial again</string>
|
<string>Show Tutorial again</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="46" column="0">
|
<item row="47" column="0">
|
||||||
<widget class="QLabel" name="labelControllerSticksAcceleration">
|
<widget class="QLabel" name="labelControllerSticksAcceleration">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Sticks Acceleration</string>
|
<string>Sticks Acceleration</string>
|
||||||
@ -972,7 +972,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="53" column="1" colspan="5">
|
<item row="54" column="1" colspan="5">
|
||||||
<widget class="QComboBox" name="comboBoxEnemyAI">
|
<widget class="QComboBox" name="comboBoxEnemyAI">
|
||||||
<property name="editable">
|
<property name="editable">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -1006,21 +1006,21 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="34" column="0">
|
<item row="35" column="0">
|
||||||
<widget class="QLabel" name="labelToleranceDistanceMouse">
|
<widget class="QLabel" name="labelToleranceDistanceMouse">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Mouse Click Tolerance</string>
|
<string>Mouse Click Tolerance</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="35" column="0">
|
<item row="36" column="0">
|
||||||
<widget class="QLabel" name="labelHandleBackRightMouseButton">
|
<widget class="QLabel" name="labelHandleBackRightMouseButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Handle back as right mouse button</string>
|
<string>Handle back as right mouse button</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="35" column="1" colspan="5">
|
<item row="36" column="1" colspan="5">
|
||||||
<widget class="QToolButton" name="buttonHandleBackRightMouseButton">
|
<widget class="QToolButton" name="buttonHandleBackRightMouseButton">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
@ -1036,7 +1036,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="53" column="0">
|
<item row="54" column="0">
|
||||||
<widget class="QLabel" name="labelEnemyAI">
|
<widget class="QLabel" name="labelEnemyAI">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enemy AI in battles</string>
|
<string>Enemy AI in battles</string>
|
||||||
@ -1050,7 +1050,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="43" column="1" colspan="5">
|
<item row="44" column="1" colspan="5">
|
||||||
<widget class="QSlider" name="sliderToleranceDistanceTouch">
|
<widget class="QSlider" name="sliderToleranceDistanceTouch">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
@ -1092,7 +1092,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="52" column="1" colspan="5">
|
<item row="53" column="1" colspan="5">
|
||||||
<widget class="QComboBox" name="comboBoxFriendlyAI">
|
<widget class="QComboBox" name="comboBoxFriendlyAI">
|
||||||
<property name="editable">
|
<property name="editable">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -1112,7 +1112,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="58" column="2" colspan="4">
|
<item row="59" column="2" colspan="4">
|
||||||
<widget class="QLineEdit" name="lineEditRepositoryExtra">
|
<widget class="QLineEdit" name="lineEditRepositoryExtra">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true"/>
|
<string notr="true"/>
|
||||||
@ -1164,7 +1164,7 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="54" column="0">
|
<item row="55" column="0">
|
||||||
<widget class="QLabel" name="labelNetwork">
|
<widget class="QLabel" name="labelNetwork">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
@ -1179,7 +1179,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="61" column="0">
|
<item row="62" column="0">
|
||||||
<widget class="QLabel" name="labelMiscellaneous">
|
<widget class="QLabel" name="labelMiscellaneous">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
@ -1194,7 +1194,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="46" column="1" colspan="5">
|
<item row="47" column="1" colspan="5">
|
||||||
<widget class="QSlider" name="sliderControllerSticksAcceleration">
|
<widget class="QSlider" name="sliderControllerSticksAcceleration">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>100</number>
|
<number>100</number>
|
||||||
@ -1266,21 +1266,21 @@ Fullscreen Exclusive Mode - the game will cover the entirety of your screen and
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="41" column="0">
|
<item row="42" column="0">
|
||||||
<widget class="QLabel" name="labelLongTouchDuration">
|
<widget class="QLabel" name="labelLongTouchDuration">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Long Touch Duration</string>
|
<string>Long Touch Duration</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="56" column="0">
|
<item row="57" column="0">
|
||||||
<widget class="QLabel" name="labelAutoCheck">
|
<widget class="QLabel" name="labelAutoCheck">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Check on startup</string>
|
<string>Check on startup</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="47" column="1" colspan="5">
|
<item row="48" column="1" colspan="5">
|
||||||
<widget class="QSlider" name="sliderToleranceDistanceController">
|
<widget class="QSlider" name="sliderToleranceDistanceController">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
@ -1324,7 +1324,7 @@ Fullscreen Exclusive Mode - the game will cover the entirety of your screen and
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="39" column="1" colspan="5">
|
<item row="40" column="1" colspan="5">
|
||||||
<widget class="QSlider" name="sliderRelativeCursorSpeed">
|
<widget class="QSlider" name="sliderRelativeCursorSpeed">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>100</number>
|
<number>100</number>
|
||||||
@ -1366,7 +1366,7 @@ Fullscreen Exclusive Mode - the game will cover the entirety of your screen and
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="34" column="1" colspan="5">
|
<item row="35" column="1" colspan="5">
|
||||||
<widget class="QSlider" name="slideToleranceDistanceMouse">
|
<widget class="QSlider" name="slideToleranceDistanceMouse">
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
@ -1439,7 +1439,7 @@ Fullscreen Exclusive Mode - the game will cover the entirety of your screen and
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="45" column="0">
|
<item row="46" column="0">
|
||||||
<widget class="QLabel" name="labelControllerSticksSensitivity">
|
<widget class="QLabel" name="labelControllerSticksSensitivity">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Sticks Sensitivity</string>
|
<string>Sticks Sensitivity</string>
|
||||||
@ -1470,7 +1470,7 @@ Fullscreen Exclusive Mode - the game will cover the entirety of your screen and
|
|||||||
<item row="12" column="1" colspan="5">
|
<item row="12" column="1" colspan="5">
|
||||||
<widget class="QComboBox" name="comboBoxResolution"/>
|
<widget class="QComboBox" name="comboBoxResolution"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="62" column="3" colspan="2">
|
<item row="63" column="3" colspan="2">
|
||||||
<widget class="QToolButton" name="buttonValidationBasic">
|
<widget class="QToolButton" name="buttonValidationBasic">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -1495,6 +1495,26 @@ Fullscreen Exclusive Mode - the game will cover the entirety of your screen and
|
|||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="33" column="0">
|
||||||
|
<widget class="QLabel" name="labelIgnoreMuteSwitch">
|
||||||
|
<property name="text">
|
||||||
|
<string>Ignore mute switch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="33" column="1" colspan="5">
|
||||||
|
<widget class="QToolButton" name="buttonIgnoreMuteSwitch">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
44
lib/AsyncRunner.h
Normal file
44
lib/AsyncRunner.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* AsyncRunner.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <tbb/task_arena.h>
|
||||||
|
#include <tbb/task_group.h>
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/// Helper class for running asynchronous tasks using TBB thread pool
|
||||||
|
class AsyncRunner : boost::noncopyable
|
||||||
|
{
|
||||||
|
tbb::task_arena arena;
|
||||||
|
tbb::task_group taskGroup;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Runs the provided functor asynchronously on a thread from the TBB worker pool.
|
||||||
|
template<typename Functor>
|
||||||
|
void run(Functor && f)
|
||||||
|
{
|
||||||
|
arena.enqueue(taskGroup.defer(std::forward<Functor>(f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Waits for all previously enqueued task.
|
||||||
|
/// Re-entrable - waiting for tasks does not prevent submitting new tasks
|
||||||
|
void wait()
|
||||||
|
{
|
||||||
|
taskGroup.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncRunner()
|
||||||
|
{
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -94,17 +94,7 @@ public:
|
|||||||
{
|
{
|
||||||
h & static_cast<CBonusSystemNode&>(*this);
|
h & static_cast<CBonusSystemNode&>(*this);
|
||||||
h & static_cast<CCombinedArtifactInstance&>(*this);
|
h & static_cast<CCombinedArtifactInstance&>(*this);
|
||||||
if (h.version >= Handler::Version::REMOVE_VLC_POINTERS)
|
|
||||||
{
|
|
||||||
h & artTypeID;
|
h & artTypeID;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool isNull = false;
|
|
||||||
h & isNull;
|
|
||||||
if (!isNull)
|
|
||||||
h & artTypeID;
|
|
||||||
}
|
|
||||||
h & id;
|
h & id;
|
||||||
BONUS_TREE_DESERIALIZATION_FIX
|
BONUS_TREE_DESERIALIZATION_FIX
|
||||||
}
|
}
|
||||||
|
@ -251,8 +251,9 @@ int CConsoleHandler::run()
|
|||||||
if ( cb )
|
if ( cb )
|
||||||
cb(buffer, false);
|
cb(buffer, false);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::unique_lock guard(shutdownMutex);
|
||||||
|
shutdownVariable.wait_for(guard, std::chrono::seconds(1));
|
||||||
|
|
||||||
if (shutdownPending)
|
if (shutdownPending)
|
||||||
return -1;
|
return -1;
|
||||||
@ -308,6 +309,7 @@ void CConsoleHandler::end()
|
|||||||
{
|
{
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
shutdownPending = true;
|
shutdownPending = true;
|
||||||
|
shutdownVariable.notify_all();
|
||||||
#else
|
#else
|
||||||
TerminateThread(thread.native_handle(),0);
|
TerminateThread(thread.native_handle(),0);
|
||||||
#endif
|
#endif
|
||||||
|
@ -94,6 +94,8 @@ private:
|
|||||||
//function to be called when message is received - string: message, bool: whether call was made from in-game console
|
//function to be called when message is received - string: message, bool: whether call was made from in-game console
|
||||||
std::function<void(const std::string &, bool)> cb;
|
std::function<void(const std::string &, bool)> cb;
|
||||||
|
|
||||||
|
std::condition_variable shutdownVariable;
|
||||||
|
std::mutex shutdownMutex;
|
||||||
std::atomic<bool> shutdownPending = false;
|
std::atomic<bool> shutdownPending = false;
|
||||||
|
|
||||||
std::mutex smx;
|
std::mutex smx;
|
||||||
|
@ -693,6 +693,7 @@ set(lib_MAIN_HEADERS
|
|||||||
|
|
||||||
AI_Base.h
|
AI_Base.h
|
||||||
ArtifactUtils.h
|
ArtifactUtils.h
|
||||||
|
AsyncRunner.h
|
||||||
BattleFieldHandler.h
|
BattleFieldHandler.h
|
||||||
CAndroidVMHelper.h
|
CAndroidVMHelper.h
|
||||||
CArtHandler.h
|
CArtHandler.h
|
||||||
|
@ -121,24 +121,8 @@ public:
|
|||||||
h & resources;
|
h & resources;
|
||||||
h & status;
|
h & status;
|
||||||
h & turnTimer;
|
h & turnTimer;
|
||||||
|
|
||||||
if (h.version >= Handler::Version::LOCAL_PLAYER_STATE_DATA)
|
|
||||||
h & *playerLocalSettings;
|
h & *playerLocalSettings;
|
||||||
|
|
||||||
if (h.version >= Handler::Version::PLAYER_STATE_OWNED_OBJECTS)
|
|
||||||
{
|
|
||||||
h & ownedObjects;
|
h & ownedObjects;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::vector<const CGObjectInstance* > heroes;
|
|
||||||
std::vector<const CGObjectInstance* > towns;
|
|
||||||
std::vector<const CGObjectInstance* > dwellings;
|
|
||||||
|
|
||||||
h & heroes;
|
|
||||||
h & towns;
|
|
||||||
h & dwellings;
|
|
||||||
}
|
|
||||||
h & quests;
|
h & quests;
|
||||||
h & visitedObjects;
|
h & visitedObjects;
|
||||||
h & visitedObjectsGlobal;
|
h & visitedObjectsGlobal;
|
||||||
@ -173,22 +157,8 @@ public:
|
|||||||
{
|
{
|
||||||
h & id;
|
h & id;
|
||||||
h & players;
|
h & players;
|
||||||
if (h.version < Handler::Version::REMOVE_FOG_OF_WAR_POINTER)
|
|
||||||
{
|
|
||||||
struct Helper : public Serializeable
|
|
||||||
{
|
|
||||||
void serialize(Handler &h) const
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
Helper helper;
|
|
||||||
auto ptrHelper = &helper;
|
|
||||||
h & ptrHelper;
|
|
||||||
}
|
|
||||||
|
|
||||||
h & fogOfWarMap;
|
h & fogOfWarMap;
|
||||||
h & static_cast<CBonusSystemNode&>(*this);
|
h & static_cast<CBonusSystemNode&>(*this);
|
||||||
|
|
||||||
if (h.version >= Handler::Version::REWARDABLE_BANKS)
|
|
||||||
h & scoutedObjects;
|
h & scoutedObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,20 +46,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
GameLibrary * LIBRARY = nullptr;
|
GameLibrary * LIBRARY = nullptr;
|
||||||
|
|
||||||
DLL_LINKAGE void preinitDLL(bool extractArchives)
|
|
||||||
{
|
|
||||||
LIBRARY = new GameLibrary();
|
|
||||||
LIBRARY->loadFilesystem(extractArchives);
|
|
||||||
settings.init("config/settings.json", "vcmi:settings");
|
|
||||||
persistentStorage.init("config/persistentStorage.json", "");
|
|
||||||
LIBRARY->loadModFilesystem();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DLL_LINKAGE void loadDLLClasses(bool onlyEssential)
|
|
||||||
{
|
|
||||||
LIBRARY->init(onlyEssential);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ArtifactService * GameLibrary::artifacts() const
|
const ArtifactService * GameLibrary::artifacts() const
|
||||||
{
|
{
|
||||||
@ -160,12 +147,21 @@ void GameLibrary::loadModFilesystem()
|
|||||||
logGlobal->info("\tMod filesystems: %d ms", loadTime.getDiff());
|
logGlobal->info("\tMod filesystems: %d ms", loadTime.getDiff());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Handler> void createHandler(std::shared_ptr<Handler> & handler)
|
template <class Handler>
|
||||||
|
void createHandler(std::unique_ptr<Handler> & handler)
|
||||||
{
|
{
|
||||||
handler = std::make_shared<Handler>();
|
handler = std::make_unique<Handler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameLibrary::init(bool onlyEssential)
|
void GameLibrary::initializeFilesystem(bool extractArchives)
|
||||||
|
{
|
||||||
|
loadFilesystem(extractArchives);
|
||||||
|
settings.init("config/settings.json", "vcmi:settings");
|
||||||
|
persistentStorage.init("config/persistentStorage.json", "");
|
||||||
|
loadModFilesystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameLibrary::initializeLibrary()
|
||||||
{
|
{
|
||||||
createHandler(settingsHandler);
|
createHandler(settingsHandler);
|
||||||
modh->initializeConfig();
|
modh->initializeConfig();
|
||||||
@ -194,7 +190,7 @@ void GameLibrary::init(bool onlyEssential)
|
|||||||
createHandler(obstacleHandler);
|
createHandler(obstacleHandler);
|
||||||
|
|
||||||
modh->load();
|
modh->load();
|
||||||
modh->afterLoad(onlyEssential);
|
modh->afterLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SCRIPTING_ENABLED
|
#if SCRIPTING_ENABLED
|
||||||
@ -207,14 +203,4 @@ void GameLibrary::scriptsLoaded()
|
|||||||
GameLibrary::GameLibrary() = default;
|
GameLibrary::GameLibrary() = default;
|
||||||
GameLibrary::~GameLibrary() = default;
|
GameLibrary::~GameLibrary() = default;
|
||||||
|
|
||||||
std::shared_ptr<CContentHandler> GameLibrary::getContent() const
|
|
||||||
{
|
|
||||||
return modh->content;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameLibrary::setContent(std::shared_ptr<CContentHandler> content)
|
|
||||||
{
|
|
||||||
modh->content = std::move(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -51,10 +51,6 @@ namespace scripting
|
|||||||
/// Loads and constructs several handlers
|
/// Loads and constructs several handlers
|
||||||
class DLL_LINKAGE GameLibrary final : public Services
|
class DLL_LINKAGE GameLibrary final : public Services
|
||||||
{
|
{
|
||||||
|
|
||||||
std::shared_ptr<CContentHandler> getContent() const;
|
|
||||||
void setContent(std::shared_ptr<CContentHandler> content);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const ArtifactService * artifacts() const override;
|
const ArtifactService * artifacts() const override;
|
||||||
const CreatureService * creatures() const override;
|
const CreatureService * creatures() const override;
|
||||||
@ -76,38 +72,44 @@ public:
|
|||||||
const IBonusTypeHandler * getBth() const; //deprecated
|
const IBonusTypeHandler * getBth() const; //deprecated
|
||||||
const CIdentifierStorage * identifiers() const;
|
const CIdentifierStorage * identifiers() const;
|
||||||
|
|
||||||
std::shared_ptr<CArtHandler> arth;
|
std::unique_ptr<CArtHandler> arth;
|
||||||
std::shared_ptr<CBonusTypeHandler> bth;
|
std::unique_ptr<CBonusTypeHandler> bth;
|
||||||
std::shared_ptr<CHeroHandler> heroh;
|
std::unique_ptr<CHeroHandler> heroh;
|
||||||
std::shared_ptr<CHeroClassHandler> heroclassesh;
|
std::unique_ptr<CHeroClassHandler> heroclassesh;
|
||||||
std::shared_ptr<CCreatureHandler> creh;
|
std::unique_ptr<CCreatureHandler> creh;
|
||||||
std::shared_ptr<CSpellHandler> spellh;
|
std::unique_ptr<CSpellHandler> spellh;
|
||||||
std::shared_ptr<CSkillHandler> skillh;
|
std::unique_ptr<CSkillHandler> skillh;
|
||||||
// TODO: Remove ObjectHandler altogether?
|
// TODO: Remove ObjectHandler altogether?
|
||||||
std::shared_ptr<CObjectHandler> objh;
|
std::unique_ptr<CObjectHandler> objh;
|
||||||
std::shared_ptr<CObjectClassesHandler> objtypeh;
|
std::unique_ptr<CObjectClassesHandler> objtypeh;
|
||||||
std::shared_ptr<CTownHandler> townh;
|
std::unique_ptr<CTownHandler> townh;
|
||||||
std::shared_ptr<CGeneralTextHandler> generaltexth;
|
std::unique_ptr<CGeneralTextHandler> generaltexth;
|
||||||
std::shared_ptr<CModHandler> modh;
|
std::unique_ptr<CModHandler> modh;
|
||||||
std::shared_ptr<TerrainTypeHandler> terrainTypeHandler;
|
std::unique_ptr<TerrainTypeHandler> terrainTypeHandler;
|
||||||
std::shared_ptr<RoadTypeHandler> roadTypeHandler;
|
std::unique_ptr<RoadTypeHandler> roadTypeHandler;
|
||||||
std::shared_ptr<RiverTypeHandler> riverTypeHandler;
|
std::unique_ptr<RiverTypeHandler> riverTypeHandler;
|
||||||
std::shared_ptr<CIdentifierStorage> identifiersHandler;
|
std::unique_ptr<CIdentifierStorage> identifiersHandler;
|
||||||
std::shared_ptr<CTerrainViewPatternConfig> terviewh;
|
std::unique_ptr<CTerrainViewPatternConfig> terviewh;
|
||||||
std::shared_ptr<CRmgTemplateStorage> tplh;
|
std::unique_ptr<CRmgTemplateStorage> tplh;
|
||||||
std::shared_ptr<BattleFieldHandler> battlefieldsHandler;
|
std::unique_ptr<BattleFieldHandler> battlefieldsHandler;
|
||||||
std::shared_ptr<ObstacleHandler> obstacleHandler;
|
std::unique_ptr<ObstacleHandler> obstacleHandler;
|
||||||
std::shared_ptr<GameSettings> settingsHandler;
|
std::unique_ptr<GameSettings> settingsHandler;
|
||||||
std::shared_ptr<ObstacleSetHandler> biomeHandler;
|
std::unique_ptr<ObstacleSetHandler> biomeHandler;
|
||||||
|
|
||||||
#if SCRIPTING_ENABLED
|
#if SCRIPTING_ENABLED
|
||||||
std::shared_ptr<scripting::ScriptHandler> scriptHandler;
|
std::unique_ptr<scripting::ScriptHandler> scriptHandler;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GameLibrary(); //c-tor, loads .lods and NULLs handlers
|
GameLibrary();
|
||||||
~GameLibrary();
|
~GameLibrary();
|
||||||
void init(bool onlyEssential); //uses standard config file
|
|
||||||
|
|
||||||
|
/// initializes settings and filesystem
|
||||||
|
void initializeFilesystem(bool extractArchives);
|
||||||
|
|
||||||
|
/// Loads all game entities
|
||||||
|
void initializeLibrary();
|
||||||
|
|
||||||
|
private:
|
||||||
// basic initialization. should be called before init(). Can also extract original H3 archives
|
// basic initialization. should be called before init(). Can also extract original H3 archives
|
||||||
void loadFilesystem(bool extractArchives);
|
void loadFilesystem(bool extractArchives);
|
||||||
void loadModFilesystem();
|
void loadModFilesystem();
|
||||||
@ -119,8 +121,4 @@ public:
|
|||||||
|
|
||||||
extern DLL_LINKAGE GameLibrary * LIBRARY;
|
extern DLL_LINKAGE GameLibrary * LIBRARY;
|
||||||
|
|
||||||
DLL_LINKAGE void preinitDLL(bool extractArchives);
|
|
||||||
DLL_LINKAGE void loadDLLClasses(bool onlyEssential = false);
|
|
||||||
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -51,11 +51,7 @@ struct DLL_LINKAGE SimturnsInfo
|
|||||||
h & requiredTurns;
|
h & requiredTurns;
|
||||||
h & optionalTurns;
|
h & optionalTurns;
|
||||||
h & allowHumanWithAI;
|
h & allowHumanWithAI;
|
||||||
|
|
||||||
if (h.version >= Handler::Version::SAVE_COMPATIBILITY_FIXES)
|
|
||||||
h & ignoreAlliedContacts;
|
h & ignoreAlliedContacts;
|
||||||
else
|
|
||||||
ignoreAlliedContacts = true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -108,14 +104,7 @@ struct DLL_LINKAGE PlayerSettings
|
|||||||
h & heroNameTextId;
|
h & heroNameTextId;
|
||||||
h & bonus;
|
h & bonus;
|
||||||
h & color;
|
h & color;
|
||||||
if (h.version >= Handler::Version::PLAYER_HANDICAP)
|
|
||||||
h & handicap;
|
h & handicap;
|
||||||
else
|
|
||||||
{
|
|
||||||
enum EHandicap {NO_HANDICAP, MILD, SEVERE};
|
|
||||||
EHandicap handicapLegacy = NO_HANDICAP;
|
|
||||||
h & handicapLegacy;
|
|
||||||
}
|
|
||||||
h & name;
|
h & name;
|
||||||
h & connectedPlayerIDs;
|
h & connectedPlayerIDs;
|
||||||
h & compOnly;
|
h & compOnly;
|
||||||
@ -173,23 +162,6 @@ struct DLL_LINKAGE StartInfo : public Serializeable
|
|||||||
h & mode;
|
h & mode;
|
||||||
h & difficulty;
|
h & difficulty;
|
||||||
h & playerInfos;
|
h & playerInfos;
|
||||||
if (h.version < Handler::Version::REMOVE_LIB_RNG)
|
|
||||||
{
|
|
||||||
uint32_t oldSeeds = 0;
|
|
||||||
h & oldSeeds;
|
|
||||||
h & oldSeeds;
|
|
||||||
h & oldSeeds;
|
|
||||||
}
|
|
||||||
if (h.version < Handler::Version::FOLDER_NAME_REWORK)
|
|
||||||
{
|
|
||||||
std::string startTimeLegacy;
|
|
||||||
h & startTimeLegacy;
|
|
||||||
struct std::tm tm;
|
|
||||||
std::istringstream ss(startTimeLegacy);
|
|
||||||
ss >> std::get_time(&tm, "%Y%m%dT%H%M%S");
|
|
||||||
startTime = mktime(&tm);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
h & startTime;
|
h & startTime;
|
||||||
h & fileURI;
|
h & fileURI;
|
||||||
h & simturnsInfo;
|
h & simturnsInfo;
|
||||||
|
@ -171,9 +171,6 @@ class VCMIDirsWIN32 final : public IVCMIDirs
|
|||||||
|
|
||||||
void VCMIDirsWIN32::init()
|
void VCMIDirsWIN32::init()
|
||||||
{
|
{
|
||||||
std::locale::global(boost::locale::generator().generate("en_US.UTF-8"));
|
|
||||||
boost::filesystem::path::imbue(std::locale());
|
|
||||||
|
|
||||||
// Call base (init dirs)
|
// Call base (init dirs)
|
||||||
IVCMIDirs::init();
|
IVCMIDirs::init();
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ public:
|
|||||||
|
|
||||||
void insert(const BattleHex & hex) noexcept
|
void insert(const BattleHex & hex) noexcept
|
||||||
{
|
{
|
||||||
if(contains(hex))
|
if(!isValidToInsert(hex))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
presenceFlags.set(hex.toInt());
|
presenceFlags.set(hex.toInt());
|
||||||
@ -86,6 +86,9 @@ public:
|
|||||||
|
|
||||||
void set(size_type index, const BattleHex & hex)
|
void set(size_type index, const BattleHex & hex)
|
||||||
{
|
{
|
||||||
|
if(!isValidToInsert(hex))
|
||||||
|
return;
|
||||||
|
|
||||||
if(index >= internalStorage.size())
|
if(index >= internalStorage.size())
|
||||||
{
|
{
|
||||||
logGlobal->error("Invalid BattleHexArray::set index parameter. It is " + std::to_string(index)
|
logGlobal->error("Invalid BattleHexArray::set index parameter. It is " + std::to_string(index)
|
||||||
@ -94,9 +97,6 @@ public:
|
|||||||
+ " and current size is " + std::to_string(internalStorage.size()));
|
+ " and current size is " + std::to_string(internalStorage.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(contains(hex))
|
|
||||||
return;
|
|
||||||
|
|
||||||
presenceFlags.set(hex.toInt());
|
presenceFlags.set(hex.toInt());
|
||||||
internalStorage[index] = hex;
|
internalStorage[index] = hex;
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ public:
|
|||||||
{
|
{
|
||||||
static const BattleHexArray invalid;
|
static const BattleHexArray invalid;
|
||||||
|
|
||||||
if (hex.isValid())
|
if(hex.isValid())
|
||||||
return allNeighbouringTiles[hex.toInt()];
|
return allNeighbouringTiles[hex.toInt()];
|
||||||
else
|
else
|
||||||
return invalid;
|
return invalid;
|
||||||
@ -209,7 +209,7 @@ public:
|
|||||||
{
|
{
|
||||||
static const BattleHexArray invalid;
|
static const BattleHexArray invalid;
|
||||||
|
|
||||||
if (hex.isValid())
|
if(hex.isValid())
|
||||||
return neighbouringTiles[hex.toInt()];
|
return neighbouringTiles[hex.toInt()];
|
||||||
else
|
else
|
||||||
return invalid;
|
return invalid;
|
||||||
@ -223,13 +223,23 @@ public:
|
|||||||
return neighbouringTilesDoubleWide.at(side)[hex.toInt()];
|
return neighbouringTilesDoubleWide.at(side)[hex.toInt()];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// note: returns true when param is ivalid BattleHex
|
[[nodiscard]] inline bool isValidToInsert(const BattleHex & hex) const noexcept
|
||||||
|
{
|
||||||
|
if(!hex.isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(contains(hex))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline bool contains(const BattleHex & hex) const noexcept
|
[[nodiscard]] inline bool contains(const BattleHex & hex) const noexcept
|
||||||
{
|
{
|
||||||
if(hex.isValid())
|
if(hex.isValid())
|
||||||
return presenceFlags.test(hex.toInt());
|
return presenceFlags.test(hex.toInt());
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Serializer>
|
template <typename Serializer>
|
||||||
|
@ -108,15 +108,6 @@ public:
|
|||||||
template <typename Handler> void serialize(Handler &h)
|
template <typename Handler> void serialize(Handler &h)
|
||||||
{
|
{
|
||||||
h & static_cast<ILimiter&>(*this);
|
h & static_cast<ILimiter&>(*this);
|
||||||
|
|
||||||
if (h.version < Handler::Version::REMOVE_TOWN_PTR)
|
|
||||||
{
|
|
||||||
bool isNull = false;
|
|
||||||
h & isNull;
|
|
||||||
if(!isNull)
|
|
||||||
h & creatureID;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
h & creatureID;
|
h & creatureID;
|
||||||
h & includeUpgrades;
|
h & includeUpgrades;
|
||||||
}
|
}
|
||||||
|
@ -46,17 +46,9 @@ class DLL_LINKAGE CampaignRegions
|
|||||||
template <typename Handler> void serialize(Handler &h)
|
template <typename Handler> void serialize(Handler &h)
|
||||||
{
|
{
|
||||||
h & infix;
|
h & infix;
|
||||||
if (h.version >= Handler::Version::REGION_LABEL)
|
|
||||||
{
|
|
||||||
h & pos;
|
h & pos;
|
||||||
h & labelPos;
|
h & labelPos;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
h & pos.x;
|
|
||||||
h & pos.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static CampaignRegions::RegionDescription fromJson(const JsonNode & node);
|
static CampaignRegions::RegionDescription fromJson(const JsonNode & node);
|
||||||
static JsonNode toJson(CampaignRegions::RegionDescription & rd);
|
static JsonNode toJson(CampaignRegions::RegionDescription & rd);
|
||||||
@ -79,12 +71,9 @@ public:
|
|||||||
h & campPrefix;
|
h & campPrefix;
|
||||||
h & colorSuffixLength;
|
h & colorSuffixLength;
|
||||||
h & regions;
|
h & regions;
|
||||||
if (h.version >= Handler::Version::CAMPAIGN_REGIONS)
|
|
||||||
{
|
|
||||||
h & campSuffix;
|
h & campSuffix;
|
||||||
h & campBackground;
|
h & campBackground;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static CampaignRegions fromJson(const JsonNode & node);
|
static CampaignRegions fromJson(const JsonNode & node);
|
||||||
static JsonNode toJson(CampaignRegions cr);
|
static JsonNode toJson(CampaignRegions cr);
|
||||||
@ -150,26 +139,19 @@ public:
|
|||||||
h & numberOfScenarios;
|
h & numberOfScenarios;
|
||||||
h & name;
|
h & name;
|
||||||
h & description;
|
h & description;
|
||||||
if (h.version >= Handler::Version::MAP_FORMAT_ADDITIONAL_INFOS)
|
|
||||||
{
|
|
||||||
h & author;
|
h & author;
|
||||||
h & authorContact;
|
h & authorContact;
|
||||||
h & campaignVersion;
|
h & campaignVersion;
|
||||||
h & creationDateTime;
|
h & creationDateTime;
|
||||||
}
|
|
||||||
h & difficultyChosenByPlayer;
|
h & difficultyChosenByPlayer;
|
||||||
h & filename;
|
h & filename;
|
||||||
h & modName;
|
h & modName;
|
||||||
h & music;
|
h & music;
|
||||||
h & encoding;
|
h & encoding;
|
||||||
h & textContainer;
|
h & textContainer;
|
||||||
if (h.version >= Handler::Version::CHRONICLES_SUPPORT)
|
|
||||||
{
|
|
||||||
h & loadingBackground;
|
h & loadingBackground;
|
||||||
h & videoRim;
|
h & videoRim;
|
||||||
h & introVideo;
|
h & introVideo;
|
||||||
}
|
|
||||||
if (h.version >= Handler::Version::CAMPAIGN_OUTRO_SUPPORT)
|
|
||||||
h & outroVideo;
|
h & outroVideo;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -374,7 +356,6 @@ public:
|
|||||||
h & chosenCampaignBonuses;
|
h & chosenCampaignBonuses;
|
||||||
h & campaignSet;
|
h & campaignSet;
|
||||||
h & mapTranslations;
|
h & mapTranslations;
|
||||||
if (h.version >= Handler::Version::HIGHSCORE_PARAMETERS)
|
|
||||||
h & highscoreParameters;
|
h & highscoreParameters;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -351,15 +351,6 @@ void CGameState::initCampaign()
|
|||||||
map = campaign->getCurrentMap();
|
map = campaign->getCurrentMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameState::generateOwnedObjectsAfterDeserialize()
|
|
||||||
{
|
|
||||||
for (auto & object : map->objects)
|
|
||||||
{
|
|
||||||
if (object && object->asOwnable() && object->getOwner().isValidPlayer())
|
|
||||||
players.at(object->getOwner()).addOwnedObject(object.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGameState::initGlobalBonuses()
|
void CGameState::initGlobalBonuses()
|
||||||
{
|
{
|
||||||
const JsonNode & baseBonuses = getSettings().getValue(EGameSettings::BONUSES_GLOBAL);
|
const JsonNode & baseBonuses = getSettings().getValue(EGameSettings::BONUSES_GLOBAL);
|
||||||
|
@ -171,20 +171,12 @@ public:
|
|||||||
h & day;
|
h & day;
|
||||||
h & map;
|
h & map;
|
||||||
h & players;
|
h & players;
|
||||||
if (h.version < Handler::Version::PLAYER_STATE_OWNED_OBJECTS)
|
|
||||||
generateOwnedObjectsAfterDeserialize();
|
|
||||||
h & teams;
|
h & teams;
|
||||||
h & heroesPool;
|
h & heroesPool;
|
||||||
h & globalEffects;
|
h & globalEffects;
|
||||||
if (h.version < Handler::Version::REMOVE_LIB_RNG)
|
|
||||||
{
|
|
||||||
std::string oldStateOfRNG;
|
|
||||||
h & oldStateOfRNG;
|
|
||||||
}
|
|
||||||
h & currentRumor;
|
h & currentRumor;
|
||||||
h & campaign;
|
h & campaign;
|
||||||
h & allocatedArtifacts;
|
h & allocatedArtifacts;
|
||||||
if (h.version >= Handler::Version::STATISTICS)
|
|
||||||
h & statistic;
|
h & statistic;
|
||||||
|
|
||||||
BONUS_TREE_DESERIALIZATION_FIX
|
BONUS_TREE_DESERIALIZATION_FIX
|
||||||
@ -213,8 +205,6 @@ private:
|
|||||||
void initVisitingAndGarrisonedHeroes();
|
void initVisitingAndGarrisonedHeroes();
|
||||||
void initCampaign();
|
void initCampaign();
|
||||||
|
|
||||||
void generateOwnedObjectsAfterDeserialize();
|
|
||||||
|
|
||||||
// ----- bonus system handling -----
|
// ----- bonus system handling -----
|
||||||
|
|
||||||
void buildBonusSystemTree();
|
void buildBonusSystemTree();
|
||||||
|
@ -63,7 +63,6 @@ struct DLL_LINKAGE StatisticDataSetEntry
|
|||||||
h & timestamp;
|
h & timestamp;
|
||||||
h & day;
|
h & day;
|
||||||
h & player;
|
h & player;
|
||||||
if(h.version >= Handler::Version::STATISTICS_SCREEN)
|
|
||||||
h & playerName;
|
h & playerName;
|
||||||
h & team;
|
h & team;
|
||||||
h & isHuman;
|
h & isHuman;
|
||||||
@ -92,11 +91,8 @@ struct DLL_LINKAGE StatisticDataSetEntry
|
|||||||
h & spentResourcesForArmy;
|
h & spentResourcesForArmy;
|
||||||
h & spentResourcesForBuildings;
|
h & spentResourcesForBuildings;
|
||||||
h & tradeVolume;
|
h & tradeVolume;
|
||||||
if(h.version >= Handler::Version::STATISTICS_SCREEN)
|
|
||||||
{
|
|
||||||
h & eventCapturedTown;
|
h & eventCapturedTown;
|
||||||
h & eventDefeatedStrongestHero;
|
h & eventDefeatedStrongestHero;
|
||||||
}
|
|
||||||
h & movementPointsUsed;
|
h & movementPointsUsed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -136,12 +132,9 @@ public:
|
|||||||
h & spentResourcesForBuildings;
|
h & spentResourcesForBuildings;
|
||||||
h & tradeVolume;
|
h & tradeVolume;
|
||||||
h & movementPointsUsed;
|
h & movementPointsUsed;
|
||||||
if(h.version >= Handler::Version::STATISTICS_SCREEN)
|
|
||||||
{
|
|
||||||
h & lastCapturedTownDay;
|
h & lastCapturedTownDay;
|
||||||
h & lastDefeatedStrongestHeroDay;
|
h & lastDefeatedStrongestHeroDay;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
std::vector<StatisticDataSetEntry> data;
|
std::vector<StatisticDataSetEntry> data;
|
||||||
std::map<PlayerColor, PlayerAccumulatedValueStorage> accumulatedValues;
|
std::map<PlayerColor, PlayerAccumulatedValueStorage> accumulatedValues;
|
||||||
|
@ -51,10 +51,7 @@ public:
|
|||||||
h & bankConfig;
|
h & bankConfig;
|
||||||
h & resetDuration;
|
h & resetDuration;
|
||||||
h & coastVisitable;
|
h & coastVisitable;
|
||||||
if (h.version >= Handler::Version::BANK_UNIT_PLACEMENT)
|
|
||||||
h & regularUnitPlacement;
|
h & regularUnitPlacement;
|
||||||
else if (!h.saving)
|
|
||||||
regularUnitPlacement = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class CBankInstanceConstructor;
|
friend class CBankInstanceConstructor;
|
||||||
|
@ -27,7 +27,7 @@ public:
|
|||||||
COMPLIANT = 0, FRIENDLY = 1, AGGRESSIVE = 2, HOSTILE = 3, SAVAGE = 4
|
COMPLIANT = 0, FRIENDLY = 1, AGGRESSIVE = 2, HOSTILE = 3, SAVAGE = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
ui32 identifier; //unique code for this monster (used in missions)
|
ui32 identifier = -1; //unique code for this monster (used in missions)
|
||||||
si8 character = 0; //character of this set of creatures (0 - the most friendly, 4 - the most hostile) => on init changed to -4 (compliant) ... 10 value (savage)
|
si8 character = 0; //character of this set of creatures (0 - the most friendly, 4 - the most hostile) => on init changed to -4 (compliant) ... 10 value (savage)
|
||||||
MetaString message; //message printed for attacking hero
|
MetaString message; //message printed for attacking hero
|
||||||
TResources resources; // resources given to hero that has won with monsters
|
TResources resources; // resources given to hero that has won with monsters
|
||||||
|
@ -371,14 +371,6 @@ public:
|
|||||||
h & skillsInfo;
|
h & skillsInfo;
|
||||||
h & visitedTown;
|
h & visitedTown;
|
||||||
h & boat;
|
h & boat;
|
||||||
if (h.version < Handler::Version::REMOVE_TOWN_PTR)
|
|
||||||
{
|
|
||||||
HeroTypeID type;
|
|
||||||
bool isNull = false;
|
|
||||||
h & isNull;
|
|
||||||
if(!isNull)
|
|
||||||
h & type;
|
|
||||||
}
|
|
||||||
h & commander;
|
h & commander;
|
||||||
h & visitedObjects;
|
h & visitedObjects;
|
||||||
BONUS_TREE_DESERIALIZATION_FIX
|
BONUS_TREE_DESERIALIZATION_FIX
|
||||||
|
@ -36,37 +36,6 @@ public:
|
|||||||
int getMarketEfficiency() const override;
|
int getMarketEfficiency() const override;
|
||||||
int availableUnits(EMarketMode mode, int marketItemSerial) const override; //-1 if unlimited
|
int availableUnits(EMarketMode mode, int marketItemSerial) const override; //-1 if unlimited
|
||||||
std::set<EMarketMode> availableModes() const override;
|
std::set<EMarketMode> availableModes() const override;
|
||||||
|
|
||||||
template <typename Handler>
|
|
||||||
void serialize(Handler &h)
|
|
||||||
{
|
|
||||||
h & static_cast<CGObjectInstance&>(*this);
|
|
||||||
if (h.version < Handler::Version::NEW_MARKETS)
|
|
||||||
{
|
|
||||||
std::set<EMarketMode> marketModes;
|
|
||||||
h & marketModes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h.version < Handler::Version::MARKET_TRANSLATION_FIX)
|
|
||||||
{
|
|
||||||
int unused = 0;
|
|
||||||
h & unused;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h.version < Handler::Version::NEW_MARKETS)
|
|
||||||
{
|
|
||||||
std::string speech;
|
|
||||||
std::string title;
|
|
||||||
h & speech;
|
|
||||||
h & title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Handler> void serializeArtifactsAltar(Handler &h)
|
|
||||||
{
|
|
||||||
serialize(h);
|
|
||||||
IMarket::serializeArtifactsAltar(h);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CGBlackMarket : public CGMarket
|
class DLL_LINKAGE CGBlackMarket : public CGMarket
|
||||||
@ -82,25 +51,8 @@ public:
|
|||||||
template <typename Handler> void serialize(Handler &h)
|
template <typename Handler> void serialize(Handler &h)
|
||||||
{
|
{
|
||||||
h & static_cast<CGMarket&>(*this);
|
h & static_cast<CGMarket&>(*this);
|
||||||
if (h.version < Handler::Version::REMOVE_VLC_POINTERS)
|
|
||||||
{
|
|
||||||
int32_t size = 0;
|
|
||||||
h & size;
|
|
||||||
for (int32_t i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
bool isNull = false;
|
|
||||||
ArtifactID artifact;
|
|
||||||
h & isNull;
|
|
||||||
if (!isNull)
|
|
||||||
h & artifact;
|
|
||||||
artifacts.push_back(artifact);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h & artifacts;
|
h & artifacts;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CGUniversity : public CGMarket
|
class DLL_LINKAGE CGUniversity : public CGMarket
|
||||||
@ -119,12 +71,6 @@ public:
|
|||||||
{
|
{
|
||||||
h & static_cast<CGMarket&>(*this);
|
h & static_cast<CGMarket&>(*this);
|
||||||
h & skills;
|
h & skills;
|
||||||
if (h.version >= Handler::Version::NEW_MARKETS && h.version < Handler::Version::MARKET_TRANSLATION_FIX)
|
|
||||||
{
|
|
||||||
std::string temp;
|
|
||||||
h & temp;
|
|
||||||
h & temp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -143,12 +143,6 @@ public:
|
|||||||
template <typename Handler> void serialize(Handler &h)
|
template <typename Handler> void serialize(Handler &h)
|
||||||
{
|
{
|
||||||
h & instanceName;
|
h & instanceName;
|
||||||
if (h.version < Handler::Version::REMOVE_OBJECT_TYPENAME)
|
|
||||||
{
|
|
||||||
std::string unused;
|
|
||||||
h & unused;
|
|
||||||
h & unused;
|
|
||||||
}
|
|
||||||
h & pos;
|
h & pos;
|
||||||
h & ID;
|
h & ID;
|
||||||
subID.serializeIdentifier(h, ID);
|
subID.serializeIdentifier(h, ID);
|
||||||
|
@ -94,43 +94,13 @@ public:
|
|||||||
h & obligatorySpells;
|
h & obligatorySpells;
|
||||||
h & spells;
|
h & spells;
|
||||||
h & events;
|
h & events;
|
||||||
|
|
||||||
if (h.version >= Handler::Version::SPELL_RESEARCH)
|
|
||||||
{
|
|
||||||
h & spellResearchCounterDay;
|
h & spellResearchCounterDay;
|
||||||
h & spellResearchAcceptedCounter;
|
h & spellResearchAcceptedCounter;
|
||||||
h & spellResearchAllowed;
|
h & spellResearchAllowed;
|
||||||
}
|
|
||||||
|
|
||||||
if (h.version >= Handler::Version::NEW_TOWN_BUILDINGS)
|
|
||||||
{
|
|
||||||
h & rewardableBuildings;
|
h & rewardableBuildings;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::vector<TownRewardableBuildingInstance*> oldVector;
|
|
||||||
h & oldVector;
|
|
||||||
rewardableBuildings = convertOldBuildings(oldVector);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h.version < Handler::Version::REMOVE_TOWN_PTR)
|
|
||||||
{
|
|
||||||
FactionID faction;
|
|
||||||
bool isNull = false;
|
|
||||||
h & isNull;
|
|
||||||
if (!isNull)
|
|
||||||
h & faction;
|
|
||||||
}
|
|
||||||
|
|
||||||
h & townAndVis;
|
h & townAndVis;
|
||||||
BONUS_TREE_DESERIALIZATION_FIX
|
BONUS_TREE_DESERIALIZATION_FIX
|
||||||
|
|
||||||
if (h.version < Handler::Version::NEW_TOWN_BUILDINGS)
|
|
||||||
{
|
|
||||||
std::set<BuildingID> overriddenBuildings;
|
|
||||||
h & overriddenBuildings;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!h.saving)
|
if(!h.saving)
|
||||||
postDeserialize();
|
postDeserialize();
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,6 @@ public:
|
|||||||
CArtifactSet * getArtifactsStorage() const;
|
CArtifactSet * getArtifactsStorage() const;
|
||||||
bool getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const; //val1 - how many units of id1 player has to give to receive val2 units
|
bool getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) const; //val1 - how many units of id1 player has to give to receive val2 units
|
||||||
|
|
||||||
template <typename Handler> void serializeArtifactsAltar(Handler &h)
|
|
||||||
{
|
|
||||||
h & *altarArtifactsStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<CArtifactSetAltar> altarArtifactsStorage;
|
std::unique_ptr<CArtifactSetAltar> altarArtifactsStorage;
|
||||||
};
|
};
|
||||||
|
@ -43,14 +43,6 @@ public:
|
|||||||
template <typename Handler> void serialize(Handler &h)
|
template <typename Handler> void serialize(Handler &h)
|
||||||
{
|
{
|
||||||
h & bID;
|
h & bID;
|
||||||
if (h.version < Handler::Version::NEW_TOWN_BUILDINGS)
|
|
||||||
{
|
|
||||||
// compatibility code
|
|
||||||
si32 indexOnTV = 0; //identifies its index on towns vector
|
|
||||||
BuildingSubID::EBuildingSubID bType = BuildingSubID::NONE;
|
|
||||||
h & indexOnTV;
|
|
||||||
h & bType;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -90,7 +82,6 @@ public:
|
|||||||
template <typename Handler> void serialize(Handler &h)
|
template <typename Handler> void serialize(Handler &h)
|
||||||
{
|
{
|
||||||
h & static_cast<TownBuildingInstance&>(*this);
|
h & static_cast<TownBuildingInstance&>(*this);
|
||||||
if (h.version >= Handler::Version::NEW_TOWN_BUILDINGS)
|
|
||||||
h & static_cast<Rewardable::Interface&>(*this);
|
h & static_cast<Rewardable::Interface&>(*this);
|
||||||
h & visitors;
|
h & visitors;
|
||||||
}
|
}
|
||||||
|
@ -192,30 +192,10 @@ public:
|
|||||||
// static members
|
// static members
|
||||||
h & obeliskCount;
|
h & obeliskCount;
|
||||||
h & obelisksVisited;
|
h & obelisksVisited;
|
||||||
|
|
||||||
if (h.version < Handler::Version::REMOVE_VLC_POINTERS)
|
|
||||||
{
|
|
||||||
int32_t size = 0;
|
|
||||||
h & size;
|
|
||||||
for (int32_t i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
bool isNull = false;
|
|
||||||
ArtifactID artifact;
|
|
||||||
h & isNull;
|
|
||||||
if (!isNull)
|
|
||||||
h & artifact;
|
|
||||||
townMerchantArtifacts.push_back(artifact);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h & townMerchantArtifacts;
|
h & townMerchantArtifacts;
|
||||||
}
|
|
||||||
h & townUniversitySkills;
|
h & townUniversitySkills;
|
||||||
|
|
||||||
h & instanceNames;
|
h & instanceNames;
|
||||||
|
|
||||||
if (h.version >= Handler::Version::PER_MAP_GAME_SETTINGS)
|
|
||||||
h & *gameSettings;
|
h & *gameSettings;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -52,27 +52,13 @@ public:
|
|||||||
h & name;
|
h & name;
|
||||||
h & message;
|
h & message;
|
||||||
h & resources;
|
h & resources;
|
||||||
if (h.version >= Handler::Version::EVENTS_PLAYER_SET)
|
|
||||||
{
|
|
||||||
h & players;
|
h & players;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ui8 playersMask = 0;
|
|
||||||
h & playersMask;
|
|
||||||
for (int i = 0; i < 8; ++i)
|
|
||||||
if ((playersMask & (1 << i)) != 0)
|
|
||||||
players.insert(PlayerColor(i));
|
|
||||||
}
|
|
||||||
h & humanAffected;
|
h & humanAffected;
|
||||||
h & computerAffected;
|
h & computerAffected;
|
||||||
h & firstOccurrence;
|
h & firstOccurrence;
|
||||||
h & nextOccurrence;
|
h & nextOccurrence;
|
||||||
if(h.version >= Handler::Version::EVENT_OBJECTS_DELETION)
|
|
||||||
{
|
|
||||||
h & deletedObjectsInstances;
|
h & deletedObjectsInstances;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
virtual void serializeJson(JsonSerializeFormat & handler);
|
virtual void serializeJson(JsonSerializeFormat & handler);
|
||||||
};
|
};
|
||||||
@ -146,50 +132,14 @@ struct DLL_LINKAGE TerrainTile
|
|||||||
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
void serialize(Handler & h)
|
void serialize(Handler & h)
|
||||||
{
|
|
||||||
if (h.version >= Handler::Version::REMOVE_VLC_POINTERS)
|
|
||||||
{
|
{
|
||||||
h & terrainType;
|
h & terrainType;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool isNull = false;
|
|
||||||
h & isNull;
|
|
||||||
if (!isNull)
|
|
||||||
h & terrainType;
|
|
||||||
}
|
|
||||||
h & terView;
|
h & terView;
|
||||||
if (h.version >= Handler::Version::REMOVE_VLC_POINTERS)
|
|
||||||
{
|
|
||||||
h & riverType;
|
h & riverType;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool isNull = false;
|
|
||||||
h & isNull;
|
|
||||||
if (!isNull)
|
|
||||||
h & riverType;
|
|
||||||
}
|
|
||||||
h & riverDir;
|
h & riverDir;
|
||||||
if (h.version >= Handler::Version::REMOVE_VLC_POINTERS)
|
|
||||||
{
|
|
||||||
h & roadType;
|
h & roadType;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool isNull = false;
|
|
||||||
h & isNull;
|
|
||||||
if (!isNull)
|
|
||||||
h & roadType;
|
|
||||||
}
|
|
||||||
h & roadDir;
|
h & roadDir;
|
||||||
h & extTileFlags;
|
h & extTileFlags;
|
||||||
if (h.version < Handler::Version::REMOVE_VLC_POINTERS)
|
|
||||||
{
|
|
||||||
bool unused = false;
|
|
||||||
h & unused;
|
|
||||||
h & unused;
|
|
||||||
}
|
|
||||||
h & visitableObjects;
|
h & visitableObjects;
|
||||||
h & blockingObjects;
|
h & blockingObjects;
|
||||||
}
|
}
|
||||||
|
@ -287,25 +287,14 @@ public:
|
|||||||
h & mods;
|
h & mods;
|
||||||
h & name;
|
h & name;
|
||||||
h & description;
|
h & description;
|
||||||
if (h.version >= Handler::Version::MAP_FORMAT_ADDITIONAL_INFOS)
|
|
||||||
{
|
|
||||||
h & author;
|
h & author;
|
||||||
h & authorContact;
|
h & authorContact;
|
||||||
h & mapVersion;
|
h & mapVersion;
|
||||||
h & creationDateTime;
|
h & creationDateTime;
|
||||||
}
|
|
||||||
h & width;
|
h & width;
|
||||||
h & height;
|
h & height;
|
||||||
h & twoLevel;
|
h & twoLevel;
|
||||||
|
|
||||||
if (h.version >= Handler::Version::SAVE_COMPATIBILITY_FIXES)
|
|
||||||
h & difficulty;
|
h & difficulty;
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t difficultyInteger = static_cast<uint8_t>(difficulty);
|
|
||||||
h & difficultyInteger;
|
|
||||||
difficulty = static_cast<EMapDifficulty>(difficultyInteger);
|
|
||||||
}
|
|
||||||
|
|
||||||
h & levelLimit;
|
h & levelLimit;
|
||||||
h & areAnyPlayers;
|
h & areAnyPlayers;
|
||||||
|
@ -48,6 +48,8 @@ void CMapInfo::mapInit(const std::string & fname)
|
|||||||
originalFileURI = resource.getOriginalName();
|
originalFileURI = resource.getOriginalName();
|
||||||
fullFileURI = boost::filesystem::canonical(*CResourceHandler::get()->getResourceName(resource)).string();
|
fullFileURI = boost::filesystem::canonical(*CResourceHandler::get()->getResourceName(resource)).string();
|
||||||
mapHeader = mapService.loadMapHeader(resource);
|
mapHeader = mapService.loadMapHeader(resource);
|
||||||
|
lastWrite = boost::filesystem::last_write_time(*CResourceHandler::get()->getResourceName(resource));
|
||||||
|
date = TextOperations::getFormattedDateTimeLocal(lastWrite);
|
||||||
countPlayers();
|
countPlayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +78,8 @@ void CMapInfo::campaignInit()
|
|||||||
originalFileURI = resource.getOriginalName();
|
originalFileURI = resource.getOriginalName();
|
||||||
fullFileURI = boost::filesystem::canonical(*CResourceHandler::get()->getResourceName(resource)).string();
|
fullFileURI = boost::filesystem::canonical(*CResourceHandler::get()->getResourceName(resource)).string();
|
||||||
campaign = CampaignHandler::getHeader(fileURI);
|
campaign = CampaignHandler::getHeader(fileURI);
|
||||||
|
lastWrite = boost::filesystem::last_write_time(*CResourceHandler::get()->getResourceName(resource));
|
||||||
|
date = TextOperations::getFormattedDateTimeLocal(lastWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMapInfo::countPlayers()
|
void CMapInfo::countPlayers()
|
||||||
|
@ -309,7 +309,7 @@ void CModHandler::load()
|
|||||||
logMod->info("\tAll game content loaded");
|
logMod->info("\tAll game content loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModHandler::afterLoad(bool onlyEssential)
|
void CModHandler::afterLoad()
|
||||||
{
|
{
|
||||||
JsonNode modSettings;
|
JsonNode modSettings;
|
||||||
for (const auto & modEntry : getActiveMods())
|
for (const auto & modEntry : getActiveMods())
|
||||||
|
@ -62,7 +62,7 @@ public:
|
|||||||
|
|
||||||
/// load content from all available mods
|
/// load content from all available mods
|
||||||
void load();
|
void load();
|
||||||
void afterLoad(bool onlyEssential);
|
void afterLoad();
|
||||||
|
|
||||||
CModHandler();
|
CModHandler();
|
||||||
~CModHandler();
|
~CModHandler();
|
||||||
|
@ -481,7 +481,6 @@ struct DLL_LINKAGE PlayerEndsGame : public CPackForClient
|
|||||||
{
|
{
|
||||||
h & player;
|
h & player;
|
||||||
h & victoryLossCheckResult;
|
h & victoryLossCheckResult;
|
||||||
if (h.version >= Handler::Version::STATISTICS_SCREEN)
|
|
||||||
h & statistic;
|
h & statistic;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -194,14 +194,9 @@ struct DLL_LINKAGE Configuration
|
|||||||
h & canRefuse;
|
h & canRefuse;
|
||||||
h & showScoutedPreview;
|
h & showScoutedPreview;
|
||||||
h & infoWindowType;
|
h & infoWindowType;
|
||||||
if (h.version >= Handler::Version::REWARDABLE_BANKS)
|
|
||||||
{
|
|
||||||
h & coastVisitable;
|
h & coastVisitable;
|
||||||
h & guardsLayout;
|
h & guardsLayout;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
coastVisitable = false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,6 @@ struct DLL_LINKAGE Reward final
|
|||||||
h & removeObject;
|
h & removeObject;
|
||||||
h & manaPercentage;
|
h & manaPercentage;
|
||||||
h & movePercentage;
|
h & movePercentage;
|
||||||
if (h.version >= Handler::Version::REWARDABLE_GUARDS)
|
|
||||||
h & guards;
|
h & guards;
|
||||||
h & heroExperience;
|
h & heroExperience;
|
||||||
h & heroLevel;
|
h & heroLevel;
|
||||||
|
@ -162,10 +162,7 @@ public:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
static_assert(!std::is_same_v<uint64_t, T>, "Serialization of unsigned 64-bit value may not work in some cases");
|
static_assert(!std::is_same_v<uint64_t, T>, "Serialization of unsigned 64-bit value may not work in some cases");
|
||||||
if (hasFeature(Version::COMPACT_INTEGER_SERIALIZATION))
|
|
||||||
data = loadEncodedInteger();
|
data = loadEncodedInteger();
|
||||||
else
|
|
||||||
this->read(static_cast<void *>(&data), sizeof(data), reverseEndianness);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,8 +440,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void load(std::string &data)
|
void load(std::string &data)
|
||||||
{
|
|
||||||
if (hasFeature(Version::COMPACT_STRING_SERIALIZATION))
|
|
||||||
{
|
{
|
||||||
int32_t length;
|
int32_t length;
|
||||||
load(length);
|
load(length);
|
||||||
@ -465,13 +460,6 @@ public:
|
|||||||
loadedStrings.push_back(data);
|
loadedStrings.push_back(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t length = readAndCheckLength();
|
|
||||||
data.resize(length);
|
|
||||||
this->read(static_cast<void *>(data.data()), length, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... TN>
|
template<typename... TN>
|
||||||
void load(std::variant<TN...> & data)
|
void load(std::variant<TN...> & data)
|
||||||
|
@ -148,10 +148,7 @@ public:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (hasFeature(Version::COMPACT_INTEGER_SERIALIZATION))
|
|
||||||
saveEncodedInteger(data);
|
saveEncodedInteger(data);
|
||||||
else
|
|
||||||
this->write(static_cast<const void *>(&data), sizeof(data));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,8 +321,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void save(const std::string &data)
|
void save(const std::string &data)
|
||||||
{
|
|
||||||
if (hasFeature(Version::COMPACT_STRING_SERIALIZATION))
|
|
||||||
{
|
{
|
||||||
if (data.empty())
|
if (data.empty())
|
||||||
{
|
{
|
||||||
@ -351,12 +346,6 @@ public:
|
|||||||
save(index);
|
save(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
save(static_cast<uint32_t>(data.length()));
|
|
||||||
this->write(static_cast<const void *>(data.data()), data.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
void save(const std::pair<T1,T2> &data)
|
void save(const std::pair<T1,T2> &data)
|
||||||
|
@ -31,47 +31,8 @@ enum class ESerializationVersion : int32_t
|
|||||||
{
|
{
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
|
|
||||||
RELEASE_150 = 840,
|
|
||||||
MINIMAL = RELEASE_150,
|
|
||||||
|
|
||||||
VOTING_SIMTURNS, // 841 - allow modification of simturns duration via vote
|
|
||||||
REMOVE_TEXT_CONTAINER_SIZE_T, // 842 Fixed serialization of size_t from text containers
|
|
||||||
BANK_UNIT_PLACEMENT, // 843 Banks have unit placement flag
|
|
||||||
|
|
||||||
RELEASE_156 = BANK_UNIT_PLACEMENT,
|
|
||||||
|
|
||||||
COMPACT_STRING_SERIALIZATION, // 844 - optimized serialization of previously encountered strings
|
|
||||||
COMPACT_INTEGER_SERIALIZATION, // 845 - serialize integers in forms similar to protobuf
|
|
||||||
REMOVE_FOG_OF_WAR_POINTER, // 846 - fog of war is serialized as reference instead of pointer
|
|
||||||
SIMPLE_TEXT_CONTAINER_SERIALIZATION, // 847 - text container is serialized using common routine instead of custom approach
|
|
||||||
MAP_FORMAT_ADDITIONAL_INFOS, // 848 - serialize new infos in map format
|
|
||||||
REMOVE_LIB_RNG, // 849 - removed random number generators from library classes
|
|
||||||
HIGHSCORE_PARAMETERS, // 850 - saves parameter for campaign
|
|
||||||
PLAYER_HANDICAP, // 851 - player handicap selection at game start
|
|
||||||
STATISTICS, // 852 - removed random number generators from library classes
|
|
||||||
CAMPAIGN_REGIONS, // 853 - configurable campaign regions
|
|
||||||
EVENTS_PLAYER_SET, // 854 - map & town events use std::set instead of bitmask to store player list
|
|
||||||
NEW_TOWN_BUILDINGS, // 855 - old bonusing buildings have been removed
|
|
||||||
STATISTICS_SCREEN, // 856 - extent statistic functions
|
|
||||||
NEW_MARKETS, // 857 - reworked market classes
|
|
||||||
PLAYER_STATE_OWNED_OBJECTS, // 858 - player state stores all owned objects in a single list
|
|
||||||
SAVE_COMPATIBILITY_FIXES, // 859 - implementation of previoulsy postponed changes to serialization
|
|
||||||
CHRONICLES_SUPPORT, // 860 - support for heroes chronicles
|
|
||||||
PER_MAP_GAME_SETTINGS, // 861 - game settings are now stored per-map
|
|
||||||
CAMPAIGN_OUTRO_SUPPORT, // 862 - support for campaign outro video
|
|
||||||
REWARDABLE_BANKS, // 863 - team state contains list of scouted objects, coast visitable rewardable objects
|
|
||||||
REGION_LABEL, // 864 - labels for campaign regions
|
|
||||||
SPELL_RESEARCH, // 865 - spell research
|
|
||||||
LOCAL_PLAYER_STATE_DATA, // 866 - player state contains arbitrary client-side data
|
|
||||||
REMOVE_TOWN_PTR, // 867 - removed pointer to CTown from CGTownInstance
|
|
||||||
REMOVE_OBJECT_TYPENAME, // 868 - remove typename from CGObjectInstance
|
|
||||||
REMOVE_VLC_POINTERS, // 869 removed remaining pointers to LIBRARY entities
|
|
||||||
FOLDER_NAME_REWORK, // 870 - rework foldername
|
|
||||||
REWARDABLE_GUARDS, // 871 - fix missing serialization of guards in rewardable objects
|
|
||||||
MARKET_TRANSLATION_FIX, // 872 - remove serialization of markets translateable strings
|
|
||||||
EVENT_OBJECTS_DELETION, //873 - allow events to remove map objects
|
|
||||||
|
|
||||||
RELEASE_160 = 873,
|
RELEASE_160 = 873,
|
||||||
|
MINIMAL = RELEASE_160,
|
||||||
|
|
||||||
MAP_HEADER_DISPOSED_HEROES, // map header contains disposed heroes list
|
MAP_HEADER_DISPOSED_HEROES, // map header contains disposed heroes list
|
||||||
|
|
||||||
|
@ -63,24 +63,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SerializerCompatibilityBonusingBuilding final : public SerializerCompatibility<TownRewardableBuildingInstance, ESerializationVersion::NEW_TOWN_BUILDINGS>
|
|
||||||
{
|
|
||||||
void loadPtr(BinaryDeserializer &ar, IGameCallback * cb, Serializeable * data) const override
|
|
||||||
{
|
|
||||||
auto * realPtr = dynamic_cast<TownRewardableBuildingInstance *>(data);
|
|
||||||
realPtr->serialize(ar);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SerializerCompatibilityArtifactsAltar final : public SerializerCompatibility<CGMarket, ESerializationVersion::NEW_MARKETS>
|
|
||||||
{
|
|
||||||
void loadPtr(BinaryDeserializer &ar, IGameCallback * cb, Serializeable * data) const override
|
|
||||||
{
|
|
||||||
auto * realPtr = dynamic_cast<CGMarket *>(data);
|
|
||||||
realPtr->serializeArtifactsAltar(ar);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void CSerializationApplier::registerType(uint16_t ID)
|
void CSerializationApplier::registerType(uint16_t ID)
|
||||||
{
|
{
|
||||||
@ -91,10 +73,6 @@ void CSerializationApplier::registerType(uint16_t ID)
|
|||||||
CSerializationApplier::CSerializationApplier()
|
CSerializationApplier::CSerializationApplier()
|
||||||
{
|
{
|
||||||
registerTypes(*this);
|
registerTypes(*this);
|
||||||
|
|
||||||
apps[54].reset(new SerializerCompatibilityBonusingBuilding);
|
|
||||||
apps[55].reset(new SerializerCompatibilityBonusingBuilding);
|
|
||||||
apps[81].reset(new SerializerCompatibilityArtifactsAltar);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSerializationApplier & CSerializationApplier::getInstance()
|
CSerializationApplier & CSerializationApplier::getInstance()
|
||||||
|
@ -263,7 +263,7 @@ void Catapult::adjustHitChance()
|
|||||||
vstd::abetween(wall, 0, 100);
|
vstd::abetween(wall, 0, 100);
|
||||||
vstd::abetween(crit, 0, 100);
|
vstd::abetween(crit, 0, 100);
|
||||||
vstd::abetween(hit, 0, 100 - crit);
|
vstd::abetween(hit, 0, 100 - crit);
|
||||||
vstd::amin(noDmg, 100 - hit - crit);
|
noDmg = 100 - hit - crit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Catapult::serializeJsonEffect(JsonSerializeFormat & handler)
|
void Catapult::serializeJsonEffect(JsonSerializeFormat & handler)
|
||||||
|
@ -66,6 +66,9 @@ struct Options
|
|||||||
/// encoding that is used by H3 for this language
|
/// encoding that is used by H3 for this language
|
||||||
std::string encoding;
|
std::string encoding;
|
||||||
|
|
||||||
|
/// proper locale name, e.g. "en_US.UTF-8"
|
||||||
|
std::string localeName;
|
||||||
|
|
||||||
/// primary IETF language tag
|
/// primary IETF language tag
|
||||||
std::string tagIETF;
|
std::string tagIETF;
|
||||||
|
|
||||||
@ -86,28 +89,28 @@ inline const auto & getLanguageList()
|
|||||||
{
|
{
|
||||||
static const std::array<Options, 22> languages
|
static const std::array<Options, 22> languages
|
||||||
{ {
|
{ {
|
||||||
{ "bulgarian", "Bulgarian", "Български", "CP1251", "bg", "bul", "%d.%m.%Y %H:%M", EPluralForms::EN_2, true },
|
{ "bulgarian", "Bulgarian", "Български", "CP1251", "bg_BG.UTF-8", "bg", "bul", "%d.%m.%Y %H:%M", EPluralForms::EN_2, true },
|
||||||
{ "czech", "Czech", "Čeština", "CP1250", "cs", "cze", "%d.%m.%Y %H:%M", EPluralForms::CZ_3, true },
|
{ "czech", "Czech", "Čeština", "CP1250", "cs_CZ.UTF-8", "cs", "cze", "%d.%m.%Y %H:%M", EPluralForms::CZ_3, true },
|
||||||
{ "chinese", "Chinese", "简体中文", "GBK", "zh", "chi", "%Y-%m-%d %H:%M", EPluralForms::VI_1, true }, // Note: actually Simplified Chinese
|
{ "chinese", "Chinese", "简体中文", "GBK", "zh_CN.UTF-8", "zh", "chi", "%Y-%m-%d %H:%M", EPluralForms::VI_1, true }, // Note: actually Simplified Chinese
|
||||||
{ "english", "English", "English", "CP1252", "en", "eng", "%Y-%m-%d %H:%M", EPluralForms::EN_2, true }, // English uses international date/time format here
|
{ "english", "English", "English", "CP1252", "en_US.UTF-8", "en", "eng", "%Y-%m-%d %H:%M", EPluralForms::EN_2, true }, // English uses international date/time format here
|
||||||
{ "finnish", "Finnish", "Suomi", "CP1252", "fi", "fin", "%d.%m.%Y %H:%M", EPluralForms::EN_2, true },
|
{ "finnish", "Finnish", "Suomi", "CP1252", "fi_FI.UTF-8", "fi", "fin", "%d.%m.%Y %H:%M", EPluralForms::EN_2, true },
|
||||||
{ "french", "French", "Français", "CP1252", "fr", "fre", "%d/%m/%Y %H:%M", EPluralForms::FR_2, true },
|
{ "french", "French", "Français", "CP1252", "fr_FR.UTF-8", "fr", "fre", "%d/%m/%Y %H:%M", EPluralForms::FR_2, true },
|
||||||
{ "german", "German", "Deutsch", "CP1252", "de", "ger", "%d.%m.%Y %H:%M", EPluralForms::EN_2, true },
|
{ "german", "German", "Deutsch", "CP1252", "de_DE.UTF-8", "de", "ger", "%d.%m.%Y %H:%M", EPluralForms::EN_2, true },
|
||||||
{ "greek", "Greek", "ελληνικά", "CP1253", "el", "ell", "%d/%m/%Y %H:%M", EPluralForms::EN_2, false },
|
{ "greek", "Greek", "ελληνικά", "CP1253", "el_GR.UTF-8", "el", "ell", "%d/%m/%Y %H:%M", EPluralForms::EN_2, false },
|
||||||
{ "hungarian", "Hungarian", "Magyar", "CP1250", "hu", "hun", "%Y. %m. %d. %H:%M", EPluralForms::EN_2, true },
|
{ "hungarian", "Hungarian", "Magyar", "CP1250", "hu_HU.UTF-8", "hu", "hun", "%Y. %m. %d. %H:%M", EPluralForms::EN_2, true },
|
||||||
{ "italian", "Italian", "Italiano", "CP1250", "it", "ita", "%d/%m/%Y %H:%M", EPluralForms::EN_2, true },
|
{ "italian", "Italian", "Italiano", "CP1250", "it_IT.UTF-8", "it", "ita", "%d/%m/%Y %H:%M", EPluralForms::EN_2, true },
|
||||||
{ "japanese", "Japanese", "日本語", "JIS", "ja", "jpn", "%Y年%m月%d日 %H:%M", EPluralForms::NONE, false },
|
{ "japanese", "Japanese", "日本語", "JIS", "ja_JP.UTF-8", "ja", "jpn", "%Y年%m月%d日 %H:%M", EPluralForms::NONE, false },
|
||||||
{ "korean", "Korean", "한국어", "CP949", "ko", "kor", "%Y-%m-%d %H:%M", EPluralForms::VI_1, true },
|
{ "korean", "Korean", "한국어", "CP949", "ko_KR.UTF-8", "ko", "kor", "%Y-%m-%d %H:%M", EPluralForms::VI_1, true },
|
||||||
{ "polish", "Polish", "Polski", "CP1250", "pl", "pol", "%d.%m.%Y %H:%M", EPluralForms::PL_3, true },
|
{ "polish", "Polish", "Polski", "CP1250", "pl_PL.UTF-8", "pl", "pol", "%d.%m.%Y %H:%M", EPluralForms::PL_3, true },
|
||||||
{ "portuguese", "Portuguese", "Português", "CP1252", "pt", "por", "%d/%m/%Y %H:%M", EPluralForms::EN_2, true }, // Note: actually Brazilian Portuguese
|
{ "portuguese", "Portuguese", "Português", "CP1252", "pt_BR.UTF-8", "pt", "por", "%d/%m/%Y %H:%M", EPluralForms::EN_2, true }, // Note: actually Brazilian Portuguese
|
||||||
{ "romanian", "Romanian", "Română", "CP28606","ro", "rum", "%Y-%m-%d %H:%M", EPluralForms::RO_3, false },
|
{ "romanian", "Romanian", "Română", "CP28606", "ro_RO.UTF-8", "ro", "rum", "%Y-%m-%d %H:%M", EPluralForms::RO_3, false },
|
||||||
{ "russian", "Russian", "Русский", "CP1251", "ru", "rus", "%d.%m.%Y %H:%M", EPluralForms::UK_3, true },
|
{ "russian", "Russian", "Русский", "CP1251", "ru_RU.UTF-8", "ru", "rus", "%d.%m.%Y %H:%M", EPluralForms::UK_3, true },
|
||||||
{ "spanish", "Spanish", "Español", "CP1252", "es", "spa", "%d/%m/%Y %H:%M", EPluralForms::EN_2, true },
|
{ "spanish", "Spanish", "Español", "CP1252", "es_ES.UTF-8", "es", "spa", "%d/%m/%Y %H:%M", EPluralForms::EN_2, true },
|
||||||
{ "swedish", "Swedish", "Svenska", "CP1252", "sv", "swe", "%Y-%m-%d %H:%M", EPluralForms::EN_2, true },
|
{ "swedish", "Swedish", "Svenska", "CP1252", "sv_SE.UTF-8", "sv", "swe", "%Y-%m-%d %H:%M", EPluralForms::EN_2, true },
|
||||||
{ "norwegian", "Norwegian", "Norsk", "CP1252", "no", "nor", "%d/%m/%Y %H:%M", EPluralForms::EN_2, false },
|
{ "norwegian", "Norwegian", "Norsk Bokmål", "UTF-8", "nb_NO.UTF-8", "nb", "nor", "%d/%m/%Y %H:%M", EPluralForms::EN_2, false },
|
||||||
{ "turkish", "Turkish", "Türkçe", "CP1254", "tr", "tur", "%d.%m.%Y %H:%M", EPluralForms::EN_2, true },
|
{ "turkish", "Turkish", "Türkçe", "CP1254", "tr_TR.UTF-8", "tr", "tur", "%d.%m.%Y %H:%M", EPluralForms::EN_2, true },
|
||||||
{ "ukrainian", "Ukrainian", "Українська", "CP1251", "uk", "ukr", "%d.%m.%Y %H:%M", EPluralForms::UK_3, true },
|
{ "ukrainian", "Ukrainian", "Українська", "CP1251", "uk_UA.UTF-8", "uk", "ukr", "%d.%m.%Y %H:%M", EPluralForms::UK_3, true },
|
||||||
{ "vietnamese", "Vietnamese", "Tiếng Việt", "UTF-8", "vi", "vie", "%d/%m/%Y %H:%M", EPluralForms::VI_1, true }, // Fan translation uses special encoding
|
{ "vietnamese", "Vietnamese", "Tiếng Việt", "UTF-8", "vi_VN.UTF-8", "vi", "vie", "%d/%m/%Y %H:%M", EPluralForms::VI_1, true }, // Fan translation uses special encoding
|
||||||
} };
|
} };
|
||||||
static_assert(languages.size() == static_cast<size_t>(ELanguages::COUNT), "Languages array is missing a value!");
|
static_assert(languages.size() == static_cast<size_t>(ELanguages::COUNT), "Languages array is missing a value!");
|
||||||
|
|
||||||
|
@ -93,46 +93,8 @@ public:
|
|||||||
void serialize(Handler & h)
|
void serialize(Handler & h)
|
||||||
{
|
{
|
||||||
std::lock_guard globalLock(globalTextMutex);
|
std::lock_guard globalLock(globalTextMutex);
|
||||||
|
|
||||||
if (h.version >= Handler::Version::SIMPLE_TEXT_CONTAINER_SERIALIZATION)
|
|
||||||
{
|
|
||||||
h & stringsLocalizations;
|
h & stringsLocalizations;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string key;
|
|
||||||
int64_t sz = stringsLocalizations.size();
|
|
||||||
|
|
||||||
if (h.version >= Handler::Version::REMOVE_TEXT_CONTAINER_SIZE_T)
|
|
||||||
{
|
|
||||||
int64_t size = sz;
|
|
||||||
h & size;
|
|
||||||
sz = size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h & sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(h.saving)
|
|
||||||
{
|
|
||||||
for(auto & s : stringsLocalizations)
|
|
||||||
{
|
|
||||||
key = s.first;
|
|
||||||
h & key;
|
|
||||||
h & s.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < sz; ++i)
|
|
||||||
{
|
|
||||||
h & key;
|
|
||||||
h & stringsLocalizations[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE TextContainerRegistrable : public TextLocalizationContainer
|
class DLL_LINKAGE TextContainerRegistrable : public TextLocalizationContainer
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "TextOperations.h"
|
#include "TextOperations.h"
|
||||||
|
|
||||||
#include "texts/CGeneralTextHandler.h"
|
#include "../GameLibrary.h"
|
||||||
|
#include "../texts/CGeneralTextHandler.h"
|
||||||
#include "Languages.h"
|
#include "Languages.h"
|
||||||
#include "CConfigHandler.h"
|
#include "CConfigHandler.h"
|
||||||
|
|
||||||
@ -252,7 +253,7 @@ std::string TextOperations::getCurrentFormattedDateTimeLocal(std::chrono::second
|
|||||||
return TextOperations::getFormattedDateTimeLocal(std::chrono::system_clock::to_time_t(timepoint));
|
return TextOperations::getFormattedDateTimeLocal(std::chrono::system_clock::to_time_t(timepoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextOperations::getLevenshteinDistance(const std::string & s, const std::string & t)
|
int TextOperations::getLevenshteinDistance(std::string_view s, std::string_view t)
|
||||||
{
|
{
|
||||||
int n = t.size();
|
int n = t.size();
|
||||||
int m = s.size();
|
int m = s.size();
|
||||||
@ -300,30 +301,51 @@ int TextOperations::getLevenshteinDistance(const std::string & s, const std::str
|
|||||||
return v0[n];
|
return v0[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextOperations::textSearchSimilar(const std::string & s, const std::string & t)
|
DLL_LINKAGE std::string TextOperations::getLocaleName()
|
||||||
{
|
{
|
||||||
boost::locale::generator gen;
|
return Languages::getLanguageOptions(LIBRARY->generaltexth->getPreferredLanguage()).localeName;
|
||||||
std::locale loc = gen("en_US.UTF-8"); // support for UTF8 lowercase
|
}
|
||||||
|
|
||||||
|
DLL_LINKAGE bool TextOperations::compareLocalizedStrings(std::string_view str1, std::string_view str2)
|
||||||
|
{
|
||||||
|
static const std::locale loc(getLocaleName());
|
||||||
|
static const std::collate<char> & col = std::use_facet<std::collate<char>>(loc);
|
||||||
|
|
||||||
|
return col.compare(str1.data(), str1.data() + str1.size(),
|
||||||
|
str2.data(), str2.data() + str2.size()) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<int> TextOperations::textSearchSimilarityScore(const std::string & s, const std::string & t)
|
||||||
|
{
|
||||||
|
static const std::locale loc = boost::locale::generator().generate(getLocaleName());
|
||||||
|
|
||||||
auto haystack = boost::locale::to_lower(t, loc);
|
auto haystack = boost::locale::to_lower(t, loc);
|
||||||
auto needle = boost::locale::to_lower(s, loc);
|
auto needle = boost::locale::to_lower(s, loc);
|
||||||
|
|
||||||
if(boost::algorithm::contains(haystack, needle))
|
// 0 - Best possible match: text starts with the search string
|
||||||
return true;
|
if(haystack.rfind(needle, 0) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if(needle.size() > haystack.size())
|
// 1 - Strong match: text contains the search string
|
||||||
return false;
|
if(haystack.find(needle) != std::string::npos)
|
||||||
|
return 1;
|
||||||
|
|
||||||
for(int i = 0; i < haystack.size() - needle.size() + 1; i++)
|
// Dynamic threshold: Reject if too many typos based on word length
|
||||||
|
int maxAllowedDistance = std::max(2, static_cast<int>(needle.size() / 2));
|
||||||
|
|
||||||
|
// Compute Levenshtein distance for fuzzy similarity
|
||||||
|
int minDist = std::numeric_limits<int>::max();
|
||||||
|
for(size_t i = 0; i <= haystack.size() - needle.size(); i++)
|
||||||
{
|
{
|
||||||
auto dist = getLevenshteinDistance(haystack.substr(i, needle.size()), needle);
|
int dist = getLevenshteinDistance(haystack.substr(i, needle.size()), needle);
|
||||||
if(needle.size() > 2 && dist <= 1)
|
minDist = std::min(minDist, dist);
|
||||||
return true;
|
|
||||||
else if(needle.size() > 4 && dist <= 2)
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
// Apply scaling: Short words tolerate smaller distances
|
||||||
|
if(needle.size() > 2 && minDist <= 2)
|
||||||
|
minDist += 1;
|
||||||
|
|
||||||
|
return (minDist > maxAllowedDistance) ? std::nullopt : std::optional<int>{ minDist };
|
||||||
}
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -74,10 +74,19 @@ namespace TextOperations
|
|||||||
/// Algorithm for detection of typos in words
|
/// Algorithm for detection of typos in words
|
||||||
/// Determines how 'different' two strings are - how many changes must be done to turn one string into another one
|
/// Determines how 'different' two strings are - how many changes must be done to turn one string into another one
|
||||||
/// https://en.wikipedia.org/wiki/Levenshtein_distance#Iterative_with_two_matrix_rows
|
/// https://en.wikipedia.org/wiki/Levenshtein_distance#Iterative_with_two_matrix_rows
|
||||||
DLL_LINKAGE int getLevenshteinDistance(const std::string & s, const std::string & t);
|
DLL_LINKAGE int getLevenshteinDistance(std::string_view s, std::string_view t);
|
||||||
|
|
||||||
|
/// Retrieves the locale name based on the selected (in config) game language.
|
||||||
|
DLL_LINKAGE std::string getLocaleName();
|
||||||
|
|
||||||
|
/// Compares two strings using locale-aware collation based on the selected game language.
|
||||||
|
DLL_LINKAGE bool compareLocalizedStrings(std::string_view str1, std::string_view str2);
|
||||||
|
|
||||||
/// Check if texts have similarity when typing into search boxes
|
/// Check if texts have similarity when typing into search boxes
|
||||||
DLL_LINKAGE bool textSearchSimilar(const std::string & s, const std::string & t);
|
/// 0 -> Exact match or starts with typed-in text, 1 -> Close match or substring match,
|
||||||
|
/// other values = Levenshtein distance, returns std::nullopt for unrelated word (bad match).
|
||||||
|
DLL_LINKAGE std::optional<int> textSearchSimilarityScore(const std::string & s, const std::string & t);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Arithmetic>
|
template<typename Arithmetic>
|
||||||
|
@ -69,16 +69,6 @@ QPixmap pixmapFromJson(const QJsonValue &val)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init()
|
|
||||||
{
|
|
||||||
loadDLLClasses();
|
|
||||||
|
|
||||||
Settings config = settings.write["session"]["editor"];
|
|
||||||
config->Bool() = true;
|
|
||||||
|
|
||||||
logGlobal->info("Initializing VCMI_Lib");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::loadUserSettings()
|
void MainWindow::loadUserSettings()
|
||||||
{
|
{
|
||||||
//load window settings
|
//load window settings
|
||||||
@ -190,7 +180,8 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||||||
logGlobal->info("The log file will be saved to %s", logPath);
|
logGlobal->info("The log file will be saved to %s", logPath);
|
||||||
|
|
||||||
//init
|
//init
|
||||||
preinitDLL(extractionOptions.extractArchives);
|
LIBRARY = new GameLibrary();
|
||||||
|
LIBRARY->initializeFilesystem(extractionOptions.extractArchives);
|
||||||
|
|
||||||
// Initialize logging based on settings
|
// Initialize logging based on settings
|
||||||
logConfig->configure();
|
logConfig->configure();
|
||||||
@ -250,7 +241,12 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||||||
loadUserSettings(); //For example window size
|
loadUserSettings(); //For example window size
|
||||||
setTitle();
|
setTitle();
|
||||||
|
|
||||||
init();
|
LIBRARY->initializeLibrary();
|
||||||
|
|
||||||
|
Settings config = settings.write["session"]["editor"];
|
||||||
|
config->Bool() = true;
|
||||||
|
|
||||||
|
logGlobal->info("Initializing VCMI_Lib");
|
||||||
|
|
||||||
graphics = new Graphics(); // should be before curh->init()
|
graphics = new Graphics(); // should be before curh->init()
|
||||||
graphics->load();//must be after Content loading but should be in main thread
|
graphics->load();//must be after Content loading but should be in main thread
|
||||||
|
@ -107,16 +107,7 @@ public:
|
|||||||
h & awaitingPlayers;
|
h & awaitingPlayers;
|
||||||
h & actingPlayers;
|
h & actingPlayers;
|
||||||
h & actedPlayers;
|
h & actedPlayers;
|
||||||
|
|
||||||
if (h.version >= Handler::Version::VOTING_SIMTURNS)
|
|
||||||
{
|
|
||||||
h & simturnsMinDurationDays;
|
h & simturnsMinDurationDays;
|
||||||
h & simturnsMaxDurationDays;
|
h & simturnsMaxDurationDays;
|
||||||
}
|
}
|
||||||
else if (!h.saving)
|
|
||||||
{
|
|
||||||
simturnsMinDurationDays.reset();
|
|
||||||
simturnsMaxDurationDays.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
@ -78,10 +78,11 @@ int main(int argc, const char * argv[])
|
|||||||
|
|
||||||
boost::program_options::variables_map opts;
|
boost::program_options::variables_map opts;
|
||||||
handleCommandOptions(argc, argv, opts);
|
handleCommandOptions(argc, argv, opts);
|
||||||
preinitDLL(false);
|
LIBRARY = new GameLibrary;
|
||||||
|
LIBRARY->initializeFilesystem(false);
|
||||||
logConfigurator.configure();
|
logConfigurator.configure();
|
||||||
|
|
||||||
loadDLLClasses();
|
LIBRARY->initializeLibrary();
|
||||||
std::srand(static_cast<uint32_t>(time(nullptr)));
|
std::srand(static_cast<uint32_t>(time(nullptr)));
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -22,8 +22,9 @@
|
|||||||
|
|
||||||
void CVcmiTestConfig::SetUp()
|
void CVcmiTestConfig::SetUp()
|
||||||
{
|
{
|
||||||
preinitDLL(true);
|
LIBRARY = new GameLibrary;
|
||||||
loadDLLClasses(true);
|
LIBRARY->initializeFilesystem(false);
|
||||||
|
LIBRARY->initializeLibrary();
|
||||||
|
|
||||||
/* TEST_DATA_DIR may be wrong, if yes below test don't run,
|
/* TEST_DATA_DIR may be wrong, if yes below test don't run,
|
||||||
find your test data folder in your build and change TEST_DATA_DIR for it*/
|
find your test data folder in your build and change TEST_DATA_DIR for it*/
|
||||||
|
Reference in New Issue
Block a user