2023-10-19 16:19:09 +02:00
/*
* CGameHandler . 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 <vcmi/Environment.h>
# include "../lib/IGameCallback.h"
# include "../lib/LoadProgress.h"
# include "../lib/ScriptHandler.h"
2024-08-14 19:24:40 +02:00
# include "../lib/gameState/GameStatistics.h"
2024-09-26 12:47:26 +02:00
# include "../lib/networkPacks/PacksForServer.h"
2023-10-19 16:19:09 +02:00
VCMI_LIB_NAMESPACE_BEGIN
struct SideInBattle ;
class IMarket ;
class SpellCastEnvironment ;
class CConnection ;
class CCommanderInstance ;
class EVictoryLossCheckResult ;
2024-06-01 17:28:17 +02:00
class CRandomGenerator ;
2023-10-19 16:19:09 +02:00
struct CPackForServer ;
struct NewTurn ;
struct CGarrisonOperationPack ;
struct SetResources ;
struct NewStructures ;
# if SCRIPTING_ENABLED
namespace scripting
{
class PoolImpl ;
}
# endif
VCMI_LIB_NAMESPACE_END
class HeroPoolProcessor ;
class CVCMIServer ;
class CBaseForGHApply ;
class PlayerMessageProcessor ;
class BattleProcessor ;
class TurnOrderProcessor ;
2024-04-26 12:26:33 +02:00
class TurnTimerHandler ;
2023-10-19 16:19:09 +02:00
class QueriesProcessor ;
class CObjectVisitQuery ;
2024-08-24 21:18:15 +02:00
class NewTurnProcessor ;
2023-10-19 16:19:09 +02:00
class CGameHandler : public IGameCallback , public Environment
{
CVCMIServer * lobby ;
public :
std : : unique_ptr < HeroPoolProcessor > heroPool ;
std : : unique_ptr < BattleProcessor > battles ;
std : : unique_ptr < QueriesProcessor > queries ;
std : : unique_ptr < TurnOrderProcessor > turnOrder ;
2024-04-26 12:15:39 +02:00
std : : unique_ptr < TurnTimerHandler > turnTimerHandler ;
2024-08-24 21:18:15 +02:00
std : : unique_ptr < NewTurnProcessor > newTurnProcessor ;
2024-06-01 17:28:17 +02:00
std : : unique_ptr < CRandomGenerator > randomNumberGenerator ;
2023-10-19 16:19:09 +02:00
//use enums as parameters, because doMove(sth, true, false, true) is not readable
enum EGuardLook { CHECK_FOR_GUARDS , IGNORE_GUARDS } ;
enum EVisitDest { VISIT_DEST , DONT_VISIT_DEST } ;
enum ELEaveTile { LEAVING_TILE , REMAINING_ON_TILE } ;
std : : unique_ptr < PlayerMessageProcessor > playerMessages ;
std : : map < PlayerColor , std : : set < std : : shared_ptr < CConnection > > > connections ; //player color -> connection to client with interface of that player
//queries stuff
ui32 QID ;
SpellCastEnvironment * spellEnv ;
const Services * services ( ) const override ;
const BattleCb * battle ( const BattleID & battleID ) const override ;
const GameCb * game ( ) const override ;
vstd : : CLoggerBase * logger ( ) const override ;
events : : EventBus * eventBus ( ) const override ;
CVCMIServer * gameLobby ( ) const ;
bool isValidObject ( const CGObjectInstance * obj ) const ;
2024-10-04 15:41:53 +02:00
bool isBlockedByQueries ( const CPackForServer * pack , PlayerColor player ) ;
2023-10-19 16:19:09 +02:00
bool isAllowedExchange ( ObjectInstanceID id1 , ObjectInstanceID id2 ) ;
void giveSpells ( const CGTownInstance * t , const CGHeroInstance * h ) ;
2024-07-12 18:51:27 +02:00
// Helpers to create new object of specified type
CGObjectInstance * createNewObject ( const int3 & visitablePosition , MapObjectID objectID , MapObjectSubID subID ) ;
void createWanderingMonster ( const int3 & visitablePosition , CreatureID creature ) ;
void createBoat ( const int3 & visitablePosition , BoatId type , PlayerColor initiator ) override ;
void createHole ( const int3 & visitablePosition , PlayerColor initiator ) ;
void newObject ( CGObjectInstance * object , PlayerColor initiator ) ;
2023-12-17 19:31:32 +02:00
explicit CGameHandler ( CVCMIServer * lobby ) ;
2023-10-19 16:19:09 +02:00
~ CGameHandler ( ) ;
//////////////////////////////////////////////////////////////////////////
//from IGameCallback
//do sth
void changeSpells ( const CGHeroInstance * hero , bool give , const std : : set < SpellID > & spells ) override ;
2024-10-10 22:31:11 +02:00
void setResearchedSpells ( const CGTownInstance * town , int level , const std : : vector < SpellID > & spells , bool accepted ) override ;
2023-10-19 16:19:09 +02:00
bool removeObject ( const CGObjectInstance * obj , const PlayerColor & initiator ) override ;
void setOwner ( const CGObjectInstance * obj , PlayerColor owner ) override ;
2024-01-04 23:57:36 +02:00
void giveExperience ( const CGHeroInstance * hero , TExpType val ) override ;
2023-10-19 16:19:09 +02:00
void changePrimSkill ( const CGHeroInstance * hero , PrimarySkill which , si64 val , bool abs = false ) override ;
void changeSecSkill ( const CGHeroInstance * hero , SecondarySkill which , int val , bool abs = false ) override ;
2024-09-04 17:14:56 +02:00
void showBlockingDialog ( const IObjectInterface * caller , BlockingDialog * iw ) override ;
2023-10-19 16:19:09 +02:00
void showTeleportDialog ( TeleportDialog * iw ) override ;
void showGarrisonDialog ( ObjectInstanceID upobj , ObjectInstanceID hid , bool removableUnits ) override ;
void showObjectWindow ( const CGObjectInstance * object , EOpenWindowMode window , const CGHeroInstance * visitor , bool addQuery ) override ;
void giveResource ( PlayerColor player , GameResID which , int val ) override ;
void giveResources ( PlayerColor player , TResources resources ) override ;
void giveCreatures ( const CArmedInstance * objid , const CGHeroInstance * h , const CCreatureSet & creatures , bool remove ) override ;
void takeCreatures ( ObjectInstanceID objid , const std : : vector < CStackBasicDescriptor > & creatures ) override ;
bool changeStackType ( const StackLocation & sl , const CCreature * c ) override ;
bool changeStackCount ( const StackLocation & sl , TQuantity count , bool absoluteValue = false ) override ;
bool insertNewStack ( const StackLocation & sl , const CCreature * c , TQuantity count ) override ;
bool eraseStack ( const StackLocation & sl , bool forceRemoval = false ) override ;
bool swapStacks ( const StackLocation & sl1 , const StackLocation & sl2 ) override ;
bool addToSlot ( const StackLocation & sl , const CCreature * c , TQuantity count ) override ;
void tryJoiningArmy ( const CArmedInstance * src , const CArmedInstance * dst , bool removeObjWhenFinished , bool allowMerging ) override ;
bool moveStack ( const StackLocation & src , const StackLocation & dst , TQuantity count = - 1 ) override ;
void removeAfterVisit ( const CGObjectInstance * object ) override ;
2024-09-04 19:39:13 +02:00
bool giveHeroNewArtifact ( const CGHeroInstance * h , const CArtifact * artType , const SpellID & spellId , const ArtifactPosition & pos ) ;
bool giveHeroNewArtifact ( const CGHeroInstance * h , const ArtifactID & artId , const ArtifactPosition & pos ) override ;
bool giveHeroNewScroll ( const CGHeroInstance * h , const SpellID & spellId , const ArtifactPosition & pos ) override ;
2024-09-06 16:59:40 +02:00
bool putArtifact ( const ArtifactLocation & al , const ArtifactInstanceID & id , std : : optional < bool > askAssemble ) override ;
2023-10-19 16:19:09 +02:00
void removeArtifact ( const ArtifactLocation & al ) override ;
2024-08-29 17:47:06 +02:00
void removeArtifact ( const ObjectInstanceID & srcId , const std : : vector < ArtifactPosition > & slotsPack ) ;
2024-03-07 16:52:50 +02:00
bool moveArtifact ( const PlayerColor & player , const ArtifactLocation & src , const ArtifactLocation & dst ) override ;
bool bulkMoveArtifacts ( const PlayerColor & player , ObjectInstanceID srcId , ObjectInstanceID dstId , bool swap , bool equipped , bool backpack ) ;
2024-09-26 12:47:26 +02:00
bool manageBackpackArtifacts ( const PlayerColor & player , const ObjectInstanceID heroID , const ManageBackpackArtifacts : : ManageCmd & sortType ) ;
2024-04-27 01:08:47 +02:00
bool saveArtifactsCostume ( const PlayerColor & player , const ObjectInstanceID heroID , uint32_t costumeIdx ) ;
bool switchArtifactsCostume ( const PlayerColor & player , const ObjectInstanceID heroID , uint32_t costumeIdx ) ;
2023-10-19 16:19:09 +02:00
bool eraseArtifactByClient ( const ArtifactLocation & al ) ;
void synchronizeArtifactHandlerLists ( ) ;
void heroVisitCastle ( const CGTownInstance * obj , const CGHeroInstance * hero ) override ;
void stopHeroVisitCastle ( const CGTownInstance * obj , const CGHeroInstance * hero ) override ;
2024-08-31 23:04:32 +02:00
void startBattle ( const CArmedInstance * army1 , const CArmedInstance * army2 , int3 tile , const CGHeroInstance * hero1 , const CGHeroInstance * hero2 , const BattleLayout & layout , const CGTownInstance * town ) override ; //use hero=nullptr for no hero
void startBattle ( const CArmedInstance * army1 , const CArmedInstance * army2 ) override ; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
2024-05-07 22:05:23 +02:00
bool moveHero ( ObjectInstanceID hid , int3 dst , EMovementMode movementMode , bool transit = false , PlayerColor asker = PlayerColor : : NEUTRAL ) override ;
2023-10-19 16:19:09 +02:00
void giveHeroBonus ( GiveBonus * bonus ) override ;
void setMovePoints ( SetMovePoints * smp ) override ;
2024-01-15 22:25:52 +02:00
void setMovePoints ( ObjectInstanceID hid , int val , bool absolute ) override ;
2023-10-19 16:19:09 +02:00
void setManaPoints ( ObjectInstanceID hid , int val ) override ;
void giveHero ( ObjectInstanceID id , PlayerColor player , ObjectInstanceID boatId = ObjectInstanceID ( ) ) override ;
void changeObjPos ( ObjectInstanceID objid , int3 newPos , const PlayerColor & initiator ) override ;
void heroExchange ( ObjectInstanceID hero1 , ObjectInstanceID hero2 ) override ;
2023-10-22 17:36:41 +02:00
void changeFogOfWar ( int3 center , ui32 radius , PlayerColor player , ETileVisibility mode ) override ;
2024-08-26 15:49:50 +02:00
void changeFogOfWar ( const std : : unordered_set < int3 > & tiles , PlayerColor player , ETileVisibility mode ) override ;
2023-10-19 16:19:09 +02:00
void castSpell ( const spells : : Caster * caster , SpellID spellID , const int3 & pos ) override ;
/// Returns hero that is currently visiting this object, or nullptr if no visit is active
const CGHeroInstance * getVisitingHero ( const CGObjectInstance * obj ) ;
2024-02-29 00:13:51 +02:00
const CGObjectInstance * getVisitingObject ( const CGHeroInstance * hero ) ;
2023-10-19 16:19:09 +02:00
bool isVisitCoveredByAnotherQuery ( const CGObjectInstance * obj , const CGHeroInstance * hero ) override ;
2023-11-06 18:27:16 +02:00
void setObjPropertyValue ( ObjectInstanceID objid , ObjProperty prop , int32_t value ) override ;
void setObjPropertyID ( ObjectInstanceID objid , ObjProperty prop , ObjPropertyID identifier ) override ;
2024-07-13 17:46:55 +02:00
void setBankObjectConfiguration ( ObjectInstanceID objid , const BankConfig & configuration ) override ;
2024-07-12 17:10:03 +02:00
void setRewardableObjectConfiguration ( ObjectInstanceID objid , const Rewardable : : Configuration & configuration ) override ;
void setRewardableObjectConfiguration ( ObjectInstanceID townInstanceID , BuildingID buildingID , const Rewardable : : Configuration & configuration ) override ;
2023-10-19 16:19:09 +02:00
void showInfoDialog ( InfoWindow * iw ) override ;
//////////////////////////////////////////////////////////////////////////
void useScholarSkill ( ObjectInstanceID hero1 , ObjectInstanceID hero2 ) ;
void setPortalDwelling ( const CGTownInstance * town , bool forced , bool clear ) ;
void visitObjectOnTile ( const TerrainTile & t , const CGHeroInstance * h ) ;
bool teleportHero ( ObjectInstanceID hid , ObjectInstanceID dstid , ui8 source , PlayerColor asker = PlayerColor : : NEUTRAL ) ;
void visitCastleObjects ( const CGTownInstance * obj , const CGHeroInstance * hero ) override ;
2024-09-15 22:09:06 +02:00
void visitCastleObjects ( const CGTownInstance * obj , std : : vector < const CGHeroInstance * > visitors ) ;
2023-10-19 16:19:09 +02:00
void levelUpHero ( const CGHeroInstance * hero , SecondarySkill skill ) ; //handle client respond and send one more request if needed
void levelUpHero ( const CGHeroInstance * hero ) ; //initial call - check if hero have remaining levelups & handle them
void levelUpCommander ( const CCommanderInstance * c , int skill ) ; //secondary skill 1 to 6, special skill : skill - 100
void levelUpCommander ( const CCommanderInstance * c ) ;
void expGiven ( const CGHeroInstance * hero ) ; //triggers needed level-ups, handles also commander of this hero
//////////////////////////////////////////////////////////////////////////
void init ( StartInfo * si , Load : : ProgressAccumulator & progressTracking ) ;
void handleClientDisconnection ( std : : shared_ptr < CConnection > c ) ;
2024-10-04 20:32:38 +02:00
void handleReceivedPack ( CPackForServer & pack ) ;
2023-10-19 16:19:09 +02:00
bool hasPlayerAt ( PlayerColor player , std : : shared_ptr < CConnection > c ) const ;
bool hasBothPlayersAtSameConnection ( PlayerColor left , PlayerColor right ) const ;
bool queryReply ( QueryID qid , std : : optional < int32_t > reply , PlayerColor player ) ;
bool buildBoat ( ObjectInstanceID objid , PlayerColor player ) ;
2023-11-06 18:27:16 +02:00
bool setFormation ( ObjectInstanceID hid , EArmyFormation formation ) ;
bool tradeResources ( const IMarket * market , ui32 amountToSell , PlayerColor player , GameResID toSell , GameResID toBuy ) ;
2023-10-19 16:19:09 +02:00
bool sacrificeCreatures ( const IMarket * market , const CGHeroInstance * hero , const std : : vector < SlotID > & slot , const std : : vector < ui32 > & count ) ;
bool sendResources ( ui32 val , PlayerColor player , GameResID r1 , PlayerColor r2 ) ;
bool sellCreatures ( ui32 count , const IMarket * market , const CGHeroInstance * hero , SlotID slot , GameResID resourceID ) ;
bool transformInUndead ( const IMarket * market , const CGHeroInstance * hero , SlotID slot ) ;
bool assembleArtifacts ( ObjectInstanceID heroID , ArtifactPosition artifactSlot , bool assemble , ArtifactID assembleTo ) ;
bool buyArtifact ( ObjectInstanceID hid , ArtifactID aid ) ; //for blacksmith and mage guild only -> buying for gold in common buildings
bool buyArtifact ( const IMarket * m , const CGHeroInstance * h , GameResID rid , ArtifactID aid ) ; //for artifact merchant and black market -> buying for any resource in special building / advobject
bool sellArtifact ( const IMarket * m , const CGHeroInstance * h , ArtifactInstanceID aid , GameResID rid ) ; //for artifact merchant selling
//void lootArtifacts (TArtHolder source, TArtHolder dest, std::vector<ui32> &arts); //after battle - move al arts to winer
bool buySecSkill ( const IMarket * m , const CGHeroInstance * h , SecondarySkill skill ) ;
bool garrisonSwap ( ObjectInstanceID tid ) ;
bool swapGarrisonOnSiege ( ObjectInstanceID tid ) override ;
bool upgradeCreature ( ObjectInstanceID objid , SlotID pos , CreatureID upgID ) ;
bool recruitCreatures ( ObjectInstanceID objid , ObjectInstanceID dst , CreatureID crid , ui32 cram , si32 level , PlayerColor player ) ;
bool buildStructure ( ObjectInstanceID tid , BuildingID bid , bool force = false ) ; //force - for events: no cost, no checkings
2024-09-03 18:31:07 +02:00
bool visitTownBuilding ( ObjectInstanceID tid , BuildingID bid ) ;
2023-10-19 16:19:09 +02:00
bool razeStructure ( ObjectInstanceID tid , BuildingID bid ) ;
2024-09-28 15:05:13 +02:00
bool spellResearch ( ObjectInstanceID tid , SpellID spellAtSlot , bool accepted ) ;
2023-10-19 16:19:09 +02:00
bool disbandCreature ( ObjectInstanceID id , SlotID pos ) ;
bool arrangeStacks ( ObjectInstanceID id1 , ObjectInstanceID id2 , ui8 what , SlotID p1 , SlotID p2 , si32 val , PlayerColor player ) ;
bool bulkMoveArmy ( ObjectInstanceID srcArmy , ObjectInstanceID destArmy , SlotID srcSlot ) ;
bool bulkSplitStack ( SlotID src , ObjectInstanceID srcOwner , si32 howMany ) ;
bool bulkMergeStacks ( SlotID slotSrc , ObjectInstanceID srcOwner ) ;
bool bulkSmartSplitStack ( SlotID slotSrc , ObjectInstanceID srcOwner ) ;
void save ( const std : : string & fname ) ;
bool load ( const std : : string & fname ) ;
void onPlayerTurnStarted ( PlayerColor which ) ;
void onPlayerTurnEnded ( PlayerColor which ) ;
void onNewTurn ( ) ;
2024-08-15 23:09:04 +02:00
void addStatistics ( StatisticDataSet & stat ) const ;
2023-10-19 16:19:09 +02:00
bool complain ( const std : : string & problem ) ; //sends message to all clients, prints on the logs and return true
void objectVisited ( const CGObjectInstance * obj , const CGHeroInstance * h ) ;
2024-09-04 16:54:09 +02:00
void objectVisitEnded ( const CGHeroInstance * h , PlayerColor player ) ;
2023-10-19 16:19:09 +02:00
bool dig ( const CGHeroInstance * h ) ;
void moveArmy ( const CArmedInstance * src , const CArmedInstance * dst , bool allowMerging ) ;
2024-01-20 20:34:51 +02:00
template < typename Handler > void serialize ( Handler & h )
2023-10-19 16:19:09 +02:00
{
h & QID ;
2024-07-19 15:57:06 +02:00
h & * randomNumberGenerator ;
2023-10-19 16:19:09 +02:00
h & * battles ;
h & * heroPool ;
h & * playerMessages ;
h & * turnOrder ;
2024-08-29 20:51:53 +02:00
h & * turnTimerHandler ;
2024-04-26 12:16:02 +02:00
2023-10-19 16:19:09 +02:00
# if SCRIPTING_ENABLED
JsonNode scriptsState ;
if ( h . saving )
serverScripts - > serializeState ( h . saving , scriptsState ) ;
h & scriptsState ;
if ( ! h . saving )
serverScripts - > serializeState ( h . saving , scriptsState ) ;
# endif
}
2024-10-04 20:59:51 +02:00
void sendToAllClients ( CPackForClient & pack ) ;
void sendAndApply ( CPackForClient & pack ) override ;
void sendAndApply ( CGarrisonOperationPack & pack ) ;
void sendAndApply ( SetResources & pack ) ;
void sendAndApply ( NewStructures & pack ) ;
2023-10-19 16:19:09 +02:00
void wrongPlayerMessage ( CPackForServer * pack , PlayerColor expectedplayer ) ;
/// Unconditionally throws with "Action not allowed" message
2024-01-13 19:39:45 +02:00
[[noreturn]] void throwNotAllowedAction ( CPackForServer * pack ) ;
2023-10-19 16:19:09 +02:00
/// Throws if player stated in pack is not making turn right now
void throwIfPlayerNotActive ( CPackForServer * pack ) ;
/// Throws if object is not owned by pack sender
void throwIfWrongOwner ( CPackForServer * pack , ObjectInstanceID id ) ;
/// Throws if player is not present on connection of this pack
void throwIfWrongPlayer ( CPackForServer * pack , PlayerColor player ) ;
void throwIfWrongPlayer ( CPackForServer * pack ) ;
2024-01-13 19:39:45 +02:00
[[noreturn]] void throwAndComplain ( CPackForServer * pack , std : : string txt ) ;
2023-10-19 16:19:09 +02:00
bool isPlayerOwns ( CPackForServer * pack , ObjectInstanceID id ) ;
2023-11-18 16:34:18 +02:00
void start ( bool resume ) ;
void tick ( int millisecondsPassed ) ;
2024-08-17 21:06:48 +02:00
bool sacrificeArtifact ( const IMarket * market , const CGHeroInstance * hero , const std : : vector < ArtifactInstanceID > & arts ) ;
2023-10-19 16:19:09 +02:00
void spawnWanderingMonsters ( CreatureID creatureID ) ;
// Check for victory and loss conditions
void checkVictoryLossConditionsForPlayer ( PlayerColor player ) ;
void checkVictoryLossConditions ( const std : : set < PlayerColor > & playerColors ) ;
void checkVictoryLossConditionsForAll ( ) ;
2024-06-01 18:09:14 +02:00
vstd : : RNG & getRandomGenerator ( ) override ;
2023-10-19 16:19:09 +02:00
# if SCRIPTING_ENABLED
scripting : : Pool * getGlobalContextPool ( ) const override ;
// scripting::Pool * getContextPool() const override;
# endif
friend class CVCMIServer ;
private :
std : : unique_ptr < events : : EventBus > serverEventBus ;
# if SCRIPTING_ENABLED
std : : shared_ptr < scripting : : PoolImpl > serverScripts ;
# endif
void reinitScripting ( ) ;
void getVictoryLossMessage ( PlayerColor player , const EVictoryLossCheckResult & victoryLossCheckResult , InfoWindow & out ) const ;
const std : : string complainNoCreatures ;
const std : : string complainNotEnoughCreatures ;
const std : : string complainInvalidSlot ;
} ;
class ExceptionNotAllowedAction : public std : : exception
{
} ;