mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Add system message about mods incompatibility
This commit is contained in:
parent
2b0f02c832
commit
e74890c4b1
@ -546,6 +546,11 @@ void CServerHandler::startCampaignScenario(std::shared_ptr<CCampaignState> cs)
|
|||||||
SDL_PushEvent(&event);
|
SDL_PushEvent(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CServerHandler::showServerError(std::string txt)
|
||||||
|
{
|
||||||
|
CInfoWindow::showInfoDialog(txt, {});
|
||||||
|
}
|
||||||
|
|
||||||
int CServerHandler::howManyPlayerInterfaces()
|
int CServerHandler::howManyPlayerInterfaces()
|
||||||
{
|
{
|
||||||
int playerInts = 0;
|
int playerInts = 0;
|
||||||
|
@ -137,6 +137,7 @@ public:
|
|||||||
void startGameplay();
|
void startGameplay();
|
||||||
void endGameplay(bool closeConnection = true, bool restart = false);
|
void endGameplay(bool closeConnection = true, bool restart = false);
|
||||||
void startCampaignScenario(std::shared_ptr<CCampaignState> cs = {});
|
void startCampaignScenario(std::shared_ptr<CCampaignState> cs = {});
|
||||||
|
void showServerError(std::string txt);
|
||||||
|
|
||||||
// TODO: LobbyState must be updated within game so we should always know how many player interfaces our client handle
|
// TODO: LobbyState must be updated within game so we should always know how many player interfaces our client handle
|
||||||
int howManyPlayerInterfaces();
|
int howManyPlayerInterfaces();
|
||||||
|
@ -137,3 +137,9 @@ void LobbyUpdateState::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler *
|
|||||||
if(hostChanged)
|
if(hostChanged)
|
||||||
lobby->toggleMode(handler->isHost());
|
lobby->toggleMode(handler->isHost());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LobbyShowMessage::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
|
||||||
|
{
|
||||||
|
lobby->buttonStart->block(false);
|
||||||
|
handler->showServerError(message);
|
||||||
|
}
|
||||||
|
@ -276,11 +276,34 @@ class DLL_LINKAGE CModHandler
|
|||||||
void loadOneMod(std::string modName, std::string parent, const JsonNode & modSettings, bool enableMods);
|
void loadOneMod(std::string modName, std::string parent, const JsonNode & modSettings, bool enableMods);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Incompatibility: public std::logic_error
|
class DLL_LINKAGE Incompatibility: public std::logic_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Incompatibility(const std::string & w): std::logic_error(w)
|
using StringPair = std::pair<const std::string, const std::string>;
|
||||||
{}
|
using ModList = std::list<StringPair>;
|
||||||
|
|
||||||
|
Incompatibility(ModList && _missingMods):
|
||||||
|
std::logic_error("Mods are required to load game"),
|
||||||
|
missingMods(std::move(_missingMods))
|
||||||
|
{
|
||||||
|
std::ostringstream _ss;
|
||||||
|
_ss << std::logic_error::what() << std::endl;
|
||||||
|
for(auto & m : missingMods)
|
||||||
|
_ss << m.first << ' ' << m.second << std::endl;
|
||||||
|
message = _ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * what() const noexcept override
|
||||||
|
{
|
||||||
|
return message.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//list of mods required to load the game
|
||||||
|
// first: mod name
|
||||||
|
// second: mod version
|
||||||
|
const ModList missingMods;
|
||||||
|
std::string message;
|
||||||
};
|
};
|
||||||
|
|
||||||
CIdentifierStorage identifiers;
|
CIdentifierStorage identifiers;
|
||||||
@ -366,7 +389,6 @@ public:
|
|||||||
{
|
{
|
||||||
h & activeMods;
|
h & activeMods;
|
||||||
for(const auto & m : activeMods)
|
for(const auto & m : activeMods)
|
||||||
|
|
||||||
h & allMods[m].version;
|
h & allMods[m].version;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -374,22 +396,22 @@ public:
|
|||||||
loadMods();
|
loadMods();
|
||||||
std::vector<TModID> newActiveMods;
|
std::vector<TModID> newActiveMods;
|
||||||
h & newActiveMods;
|
h & newActiveMods;
|
||||||
|
|
||||||
|
Incompatibility::ModList missingMods;
|
||||||
for(auto & m : newActiveMods)
|
for(auto & m : newActiveMods)
|
||||||
{
|
{
|
||||||
if(!allMods.count(m))
|
|
||||||
throw Incompatibility(m + " unkown mod");
|
|
||||||
|
|
||||||
CModInfo::Version mver;
|
CModInfo::Version mver;
|
||||||
h & mver;
|
h & mver;
|
||||||
if(!allMods[m].version.isNull() && !mver.isNull() && !allMods[m].version.compatible(mver))
|
|
||||||
{
|
if(allMods.count(m) && (allMods[m].version.isNull() || mver.isNull() || allMods[m].version.compatible(mver)))
|
||||||
std::string err = allMods[m].name +
|
allMods[m].enabled = true;
|
||||||
": version needed " + mver.toString() +
|
else
|
||||||
"but you have installed " + allMods[m].version.toString();
|
missingMods.emplace_back(m, mver.toString());
|
||||||
throw Incompatibility(err);
|
|
||||||
}
|
|
||||||
allMods[m].enabled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!missingMods.empty())
|
||||||
|
throw Incompatibility(std::move(missingMods));
|
||||||
|
|
||||||
std::swap(activeMods, newActiveMods);
|
std::swap(activeMods, newActiveMods);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,3 +309,15 @@ struct LobbyForceSetPlayer : public CLobbyPackToServer
|
|||||||
h & targetPlayerColor;
|
h & targetPlayerColor;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LobbyShowMessage : public CLobbyPackToPropagate
|
||||||
|
{
|
||||||
|
std::string message;
|
||||||
|
|
||||||
|
void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler);
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & message;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -374,6 +374,7 @@ void registerTypesLobbyPacks(Serializer &s)
|
|||||||
s.template registerType<CLobbyPackToPropagate, LobbyChangeHost>();
|
s.template registerType<CLobbyPackToPropagate, LobbyChangeHost>();
|
||||||
// Only server send
|
// Only server send
|
||||||
s.template registerType<CLobbyPackToPropagate, LobbyUpdateState>();
|
s.template registerType<CLobbyPackToPropagate, LobbyUpdateState>();
|
||||||
|
s.template registerType<CLobbyPackToPropagate, LobbyShowMessage>();
|
||||||
|
|
||||||
// For client with permissions
|
// For client with permissions
|
||||||
s.template registerType<CLobbyPackToServer, LobbyChangePlayerOption>();
|
s.template registerType<CLobbyPackToServer, LobbyChangePlayerOption>();
|
||||||
|
@ -2967,7 +2967,7 @@ void CGameHandler::save(const std::string & filename)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameHandler::load(const std::string & filename)
|
bool CGameHandler::load(const std::string & filename)
|
||||||
{
|
{
|
||||||
logGlobal->info("Loading from %s", filename);
|
logGlobal->info("Loading from %s", filename);
|
||||||
const auto stem = FileInfo::GetPathStem(filename);
|
const auto stem = FileInfo::GetPathStem(filename);
|
||||||
@ -2984,12 +2984,20 @@ void CGameHandler::load(const std::string & filename)
|
|||||||
}
|
}
|
||||||
logGlobal->info("Game has been successfully loaded!");
|
logGlobal->info("Game has been successfully loaded!");
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(const CModHandler::Incompatibility & e)
|
||||||
{
|
{
|
||||||
logGlobal->error("Failed to load game: %s", e.what());
|
logGlobal->error("Failed to load game: %s", e.what());
|
||||||
|
lobby->announceMessage(e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch(const std::exception & e)
|
||||||
|
{
|
||||||
|
logGlobal->error("Failed to load game: %s", e.what());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
gs->preInit(VLC);
|
gs->preInit(VLC);
|
||||||
gs->updateOnLoad(lobby->si.get());
|
gs->updateOnLoad(lobby->si.get());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGameHandler::bulkSplitStack(SlotID slotSrc, ObjectInstanceID srcOwner, si32 howMany)
|
bool CGameHandler::bulkSplitStack(SlotID slotSrc, ObjectInstanceID srcOwner, si32 howMany)
|
||||||
|
@ -257,7 +257,7 @@ public:
|
|||||||
bool bulkMergeStacks(SlotID slotSrc, ObjectInstanceID srcOwner);
|
bool bulkMergeStacks(SlotID slotSrc, ObjectInstanceID srcOwner);
|
||||||
bool bulkSmartSplitStack(SlotID slotSrc, ObjectInstanceID srcOwner);
|
bool bulkSmartSplitStack(SlotID slotSrc, ObjectInstanceID srcOwner);
|
||||||
void save(const std::string &fname);
|
void save(const std::string &fname);
|
||||||
void load(const std::string &fname);
|
bool load(const std::string &fname);
|
||||||
|
|
||||||
void handleTimeEvents();
|
void handleTimeEvents();
|
||||||
void handleTownEvents(CGTownInstance *town, NewTurn &n);
|
void handleTownEvents(CGTownInstance *town, NewTurn &n);
|
||||||
|
@ -223,7 +223,7 @@ void CVCMIServer::threadAnnounceLobby()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVCMIServer::prepareToStartGame()
|
bool CVCMIServer::prepareToStartGame()
|
||||||
{
|
{
|
||||||
if(state == EServerState::GAMEPLAY)
|
if(state == EServerState::GAMEPLAY)
|
||||||
{
|
{
|
||||||
@ -234,8 +234,9 @@ void CVCMIServer::prepareToStartGame()
|
|||||||
// FIXME: dirry hack to make sure old CGameHandler::run is finished
|
// FIXME: dirry hack to make sure old CGameHandler::run is finished
|
||||||
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
|
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
|
||||||
}
|
}
|
||||||
state = EServerState::GAMEPLAY_STARTING;
|
|
||||||
gh = std::make_shared<CGameHandler>(this);
|
if(!gh)
|
||||||
|
gh = std::make_shared<CGameHandler>(this);
|
||||||
switch(si->mode)
|
switch(si->mode)
|
||||||
{
|
{
|
||||||
case StartInfo::CAMPAIGN:
|
case StartInfo::CAMPAIGN:
|
||||||
@ -252,13 +253,17 @@ void CVCMIServer::prepareToStartGame()
|
|||||||
|
|
||||||
case StartInfo::LOAD_GAME:
|
case StartInfo::LOAD_GAME:
|
||||||
logNetwork->info("Preparing to start loaded game");
|
logNetwork->info("Preparing to start loaded game");
|
||||||
gh->load(si->mapname);
|
if(!gh->load(si->mapname))
|
||||||
|
return false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logNetwork->error("Wrong mode in StartInfo!");
|
logNetwork->error("Wrong mode in StartInfo!");
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = EServerState::GAMEPLAY_STARTING;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVCMIServer::startGameImmidiately()
|
void CVCMIServer::startGameImmidiately()
|
||||||
@ -384,6 +389,14 @@ void CVCMIServer::announcePack(std::unique_ptr<CPackForLobby> pack)
|
|||||||
applier->getApplier(typeList.getTypeID(pack.get()))->applyOnServerAfter(this, pack.get());
|
applier->getApplier(typeList.getTypeID(pack.get()))->applyOnServerAfter(this, pack.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CVCMIServer::announceMessage(const std::string & txt)
|
||||||
|
{
|
||||||
|
logNetwork->info("Show message: %s", txt);
|
||||||
|
auto cm = vstd::make_unique<LobbyShowMessage>();
|
||||||
|
cm->message = txt;
|
||||||
|
addToAnnounceQueue(std::move(cm));
|
||||||
|
}
|
||||||
|
|
||||||
void CVCMIServer::announceTxt(const std::string & txt, const std::string & playerName)
|
void CVCMIServer::announceTxt(const std::string & txt, const std::string & playerName)
|
||||||
{
|
{
|
||||||
logNetwork->info("%s says: %s", playerName, txt);
|
logNetwork->info("%s says: %s", playerName, txt);
|
||||||
|
@ -63,7 +63,7 @@ public:
|
|||||||
CVCMIServer(boost::program_options::variables_map & opts);
|
CVCMIServer(boost::program_options::variables_map & opts);
|
||||||
~CVCMIServer();
|
~CVCMIServer();
|
||||||
void run();
|
void run();
|
||||||
void prepareToStartGame();
|
bool prepareToStartGame();
|
||||||
void startGameImmidiately();
|
void startGameImmidiately();
|
||||||
|
|
||||||
void startAsyncAccept();
|
void startAsyncAccept();
|
||||||
@ -76,6 +76,7 @@ public:
|
|||||||
bool passHost(int toConnectionId);
|
bool passHost(int toConnectionId);
|
||||||
|
|
||||||
void announceTxt(const std::string & txt, const std::string & playerName = "system");
|
void announceTxt(const std::string & txt, const std::string & playerName = "system");
|
||||||
|
void announceMessage(const std::string & txt);
|
||||||
void addToAnnounceQueue(std::unique_ptr<CPackForLobby> pack);
|
void addToAnnounceQueue(std::unique_ptr<CPackForLobby> pack);
|
||||||
|
|
||||||
void setPlayerConnectedId(PlayerSettings & pset, ui8 player) const;
|
void setPlayerConnectedId(PlayerSettings & pset, ui8 player) const;
|
||||||
|
@ -177,7 +177,9 @@ bool LobbyStartGame::applyOnServer(CVCMIServer * srv)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Server will prepare gamestate and we announce StartInfo to clients
|
// Server will prepare gamestate and we announce StartInfo to clients
|
||||||
srv->prepareToStartGame();
|
if(!srv->prepareToStartGame())
|
||||||
|
return false;
|
||||||
|
|
||||||
initializedStartInfo = std::make_shared<StartInfo>(*srv->gh->getStartInfo(true));
|
initializedStartInfo = std::make_shared<StartInfo>(*srv->gh->getStartInfo(true));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user