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);
|
||||
}
|
||||
|
||||
void CServerHandler::showServerError(std::string txt)
|
||||
{
|
||||
CInfoWindow::showInfoDialog(txt, {});
|
||||
}
|
||||
|
||||
int CServerHandler::howManyPlayerInterfaces()
|
||||
{
|
||||
int playerInts = 0;
|
||||
|
@ -137,6 +137,7 @@ public:
|
||||
void startGameplay();
|
||||
void endGameplay(bool closeConnection = true, bool restart = false);
|
||||
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
|
||||
int howManyPlayerInterfaces();
|
||||
|
@ -137,3 +137,9 @@ void LobbyUpdateState::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler *
|
||||
if(hostChanged)
|
||||
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);
|
||||
public:
|
||||
|
||||
class Incompatibility: public std::logic_error
|
||||
class DLL_LINKAGE Incompatibility: public std::logic_error
|
||||
{
|
||||
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;
|
||||
@ -366,7 +389,6 @@ public:
|
||||
{
|
||||
h & activeMods;
|
||||
for(const auto & m : activeMods)
|
||||
|
||||
h & allMods[m].version;
|
||||
}
|
||||
else
|
||||
@ -374,22 +396,22 @@ public:
|
||||
loadMods();
|
||||
std::vector<TModID> newActiveMods;
|
||||
h & newActiveMods;
|
||||
|
||||
Incompatibility::ModList missingMods;
|
||||
for(auto & m : newActiveMods)
|
||||
{
|
||||
if(!allMods.count(m))
|
||||
throw Incompatibility(m + " unkown mod");
|
||||
|
||||
CModInfo::Version mver;
|
||||
h & mver;
|
||||
if(!allMods[m].version.isNull() && !mver.isNull() && !allMods[m].version.compatible(mver))
|
||||
{
|
||||
std::string err = allMods[m].name +
|
||||
": version needed " + mver.toString() +
|
||||
"but you have installed " + allMods[m].version.toString();
|
||||
throw Incompatibility(err);
|
||||
}
|
||||
allMods[m].enabled = true;
|
||||
|
||||
if(allMods.count(m) && (allMods[m].version.isNull() || mver.isNull() || allMods[m].version.compatible(mver)))
|
||||
allMods[m].enabled = true;
|
||||
else
|
||||
missingMods.emplace_back(m, mver.toString());
|
||||
}
|
||||
|
||||
if(!missingMods.empty())
|
||||
throw Incompatibility(std::move(missingMods));
|
||||
|
||||
std::swap(activeMods, newActiveMods);
|
||||
}
|
||||
|
||||
|
@ -309,3 +309,15 @@ struct LobbyForceSetPlayer : public CLobbyPackToServer
|
||||
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>();
|
||||
// Only server send
|
||||
s.template registerType<CLobbyPackToPropagate, LobbyUpdateState>();
|
||||
s.template registerType<CLobbyPackToPropagate, LobbyShowMessage>();
|
||||
|
||||
// For client with permissions
|
||||
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);
|
||||
const auto stem = FileInfo::GetPathStem(filename);
|
||||
@ -2984,12 +2984,20 @@ void CGameHandler::load(const std::string & filename)
|
||||
}
|
||||
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());
|
||||
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->updateOnLoad(lobby->si.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameHandler::bulkSplitStack(SlotID slotSrc, ObjectInstanceID srcOwner, si32 howMany)
|
||||
|
@ -257,7 +257,7 @@ public:
|
||||
bool bulkMergeStacks(SlotID slotSrc, ObjectInstanceID srcOwner);
|
||||
bool bulkSmartSplitStack(SlotID slotSrc, ObjectInstanceID srcOwner);
|
||||
void save(const std::string &fname);
|
||||
void load(const std::string &fname);
|
||||
bool load(const std::string &fname);
|
||||
|
||||
void handleTimeEvents();
|
||||
void handleTownEvents(CGTownInstance *town, NewTurn &n);
|
||||
|
@ -223,7 +223,7 @@ void CVCMIServer::threadAnnounceLobby()
|
||||
}
|
||||
}
|
||||
|
||||
void CVCMIServer::prepareToStartGame()
|
||||
bool CVCMIServer::prepareToStartGame()
|
||||
{
|
||||
if(state == EServerState::GAMEPLAY)
|
||||
{
|
||||
@ -234,8 +234,9 @@ void CVCMIServer::prepareToStartGame()
|
||||
// FIXME: dirry hack to make sure old CGameHandler::run is finished
|
||||
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)
|
||||
{
|
||||
case StartInfo::CAMPAIGN:
|
||||
@ -252,13 +253,17 @@ void CVCMIServer::prepareToStartGame()
|
||||
|
||||
case StartInfo::LOAD_GAME:
|
||||
logNetwork->info("Preparing to start loaded game");
|
||||
gh->load(si->mapname);
|
||||
if(!gh->load(si->mapname))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
logNetwork->error("Wrong mode in StartInfo!");
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
state = EServerState::GAMEPLAY_STARTING;
|
||||
return true;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
logNetwork->info("%s says: %s", playerName, txt);
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
CVCMIServer(boost::program_options::variables_map & opts);
|
||||
~CVCMIServer();
|
||||
void run();
|
||||
void prepareToStartGame();
|
||||
bool prepareToStartGame();
|
||||
void startGameImmidiately();
|
||||
|
||||
void startAsyncAccept();
|
||||
@ -76,6 +76,7 @@ public:
|
||||
bool passHost(int toConnectionId);
|
||||
|
||||
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 setPlayerConnectedId(PlayerSettings & pset, ui8 player) const;
|
||||
|
@ -177,7 +177,9 @@ bool LobbyStartGame::applyOnServer(CVCMIServer * srv)
|
||||
return false;
|
||||
}
|
||||
// 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));
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user